C# type parameter only reads as base class



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








0















I have a base class I'll call TypeBase and several classes derived from it, for grins lets call them TypeImage and TypeAsset. Here's what happens in the code:



...
TypeBase b = null;
MethodDoingStuff(passedID, ref b);
RepositoryCall(b, otherArgs);


So in MethodDoingStuff we have something like this:



public bool MethodDoingStuff (long passedID, ref TypeBase b)

object concrete = DbCallThatGetsSubclass(passedID);//returns a subclass
of TypeBase(in reality more than 2 possibilities)
TypeBase tb = (TypeBase)concrete;
b=tb;
return true;



So the method sig for the Repository call looks like this:



 public virtual T FindByID<T>( T typeInstance, long id) where T : TypeBase

T item = (T)Activator.CreateInstance(typeof(T));

using (IDbConnection cn = Connection)

item = cn.Get<T>(id);


return item;



The problem arises in that cn.Get<T>(id) is a call to a Dapper Extension, the Table it looks for is based on that type parameter, which of course it sees as TypeBase. The relevant table data is of course in the tables TypeImage or TypeAsset, or whatever. My freedom mostly lies in the Repository: I can change how the method works or introduce overloads. I can also change what arguments are passed into MethodDoingStuff() but for a variety of reasons can't really change MethodDoingStuff itself.










share|improve this question






















  • Method calls are resolved at compile time. But you're expecting it to somehow pick up runtime information. That's the main issue here. You can use dynamic but that's an ugly crutch. Ideally, you change things around so that everything is generic in the appropriate type parameter.

    – Damien_The_Unbeliever
    Nov 15 '18 at 17:39











  • You are right that it's wrong to expect it to know run time types, but that's what I'm trying to get around. Where would I use dynamic exactly?

    – greedyLump
    Nov 15 '18 at 17:56

















0















I have a base class I'll call TypeBase and several classes derived from it, for grins lets call them TypeImage and TypeAsset. Here's what happens in the code:



...
TypeBase b = null;
MethodDoingStuff(passedID, ref b);
RepositoryCall(b, otherArgs);


So in MethodDoingStuff we have something like this:



public bool MethodDoingStuff (long passedID, ref TypeBase b)

object concrete = DbCallThatGetsSubclass(passedID);//returns a subclass
of TypeBase(in reality more than 2 possibilities)
TypeBase tb = (TypeBase)concrete;
b=tb;
return true;



So the method sig for the Repository call looks like this:



 public virtual T FindByID<T>( T typeInstance, long id) where T : TypeBase

T item = (T)Activator.CreateInstance(typeof(T));

using (IDbConnection cn = Connection)

item = cn.Get<T>(id);


return item;



The problem arises in that cn.Get<T>(id) is a call to a Dapper Extension, the Table it looks for is based on that type parameter, which of course it sees as TypeBase. The relevant table data is of course in the tables TypeImage or TypeAsset, or whatever. My freedom mostly lies in the Repository: I can change how the method works or introduce overloads. I can also change what arguments are passed into MethodDoingStuff() but for a variety of reasons can't really change MethodDoingStuff itself.










share|improve this question






















  • Method calls are resolved at compile time. But you're expecting it to somehow pick up runtime information. That's the main issue here. You can use dynamic but that's an ugly crutch. Ideally, you change things around so that everything is generic in the appropriate type parameter.

    – Damien_The_Unbeliever
    Nov 15 '18 at 17:39











  • You are right that it's wrong to expect it to know run time types, but that's what I'm trying to get around. Where would I use dynamic exactly?

    – greedyLump
    Nov 15 '18 at 17:56













0












0








0


0






I have a base class I'll call TypeBase and several classes derived from it, for grins lets call them TypeImage and TypeAsset. Here's what happens in the code:



...
TypeBase b = null;
MethodDoingStuff(passedID, ref b);
RepositoryCall(b, otherArgs);


So in MethodDoingStuff we have something like this:



public bool MethodDoingStuff (long passedID, ref TypeBase b)

object concrete = DbCallThatGetsSubclass(passedID);//returns a subclass
of TypeBase(in reality more than 2 possibilities)
TypeBase tb = (TypeBase)concrete;
b=tb;
return true;



So the method sig for the Repository call looks like this:



 public virtual T FindByID<T>( T typeInstance, long id) where T : TypeBase

T item = (T)Activator.CreateInstance(typeof(T));

using (IDbConnection cn = Connection)

item = cn.Get<T>(id);


return item;



The problem arises in that cn.Get<T>(id) is a call to a Dapper Extension, the Table it looks for is based on that type parameter, which of course it sees as TypeBase. The relevant table data is of course in the tables TypeImage or TypeAsset, or whatever. My freedom mostly lies in the Repository: I can change how the method works or introduce overloads. I can also change what arguments are passed into MethodDoingStuff() but for a variety of reasons can't really change MethodDoingStuff itself.










share|improve this question














I have a base class I'll call TypeBase and several classes derived from it, for grins lets call them TypeImage and TypeAsset. Here's what happens in the code:



...
TypeBase b = null;
MethodDoingStuff(passedID, ref b);
RepositoryCall(b, otherArgs);


So in MethodDoingStuff we have something like this:



public bool MethodDoingStuff (long passedID, ref TypeBase b)

object concrete = DbCallThatGetsSubclass(passedID);//returns a subclass
of TypeBase(in reality more than 2 possibilities)
TypeBase tb = (TypeBase)concrete;
b=tb;
return true;



So the method sig for the Repository call looks like this:



 public virtual T FindByID<T>( T typeInstance, long id) where T : TypeBase

T item = (T)Activator.CreateInstance(typeof(T));

using (IDbConnection cn = Connection)

item = cn.Get<T>(id);


return item;



The problem arises in that cn.Get<T>(id) is a call to a Dapper Extension, the Table it looks for is based on that type parameter, which of course it sees as TypeBase. The relevant table data is of course in the tables TypeImage or TypeAsset, or whatever. My freedom mostly lies in the Repository: I can change how the method works or introduce overloads. I can also change what arguments are passed into MethodDoingStuff() but for a variety of reasons can't really change MethodDoingStuff itself.







c# generics dapper-contrib






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 15 '18 at 17:17









greedyLumpgreedyLump

40111




40111












  • Method calls are resolved at compile time. But you're expecting it to somehow pick up runtime information. That's the main issue here. You can use dynamic but that's an ugly crutch. Ideally, you change things around so that everything is generic in the appropriate type parameter.

    – Damien_The_Unbeliever
    Nov 15 '18 at 17:39











  • You are right that it's wrong to expect it to know run time types, but that's what I'm trying to get around. Where would I use dynamic exactly?

    – greedyLump
    Nov 15 '18 at 17:56

















  • Method calls are resolved at compile time. But you're expecting it to somehow pick up runtime information. That's the main issue here. You can use dynamic but that's an ugly crutch. Ideally, you change things around so that everything is generic in the appropriate type parameter.

    – Damien_The_Unbeliever
    Nov 15 '18 at 17:39











  • You are right that it's wrong to expect it to know run time types, but that's what I'm trying to get around. Where would I use dynamic exactly?

    – greedyLump
    Nov 15 '18 at 17:56
















Method calls are resolved at compile time. But you're expecting it to somehow pick up runtime information. That's the main issue here. You can use dynamic but that's an ugly crutch. Ideally, you change things around so that everything is generic in the appropriate type parameter.

– Damien_The_Unbeliever
Nov 15 '18 at 17:39





Method calls are resolved at compile time. But you're expecting it to somehow pick up runtime information. That's the main issue here. You can use dynamic but that's an ugly crutch. Ideally, you change things around so that everything is generic in the appropriate type parameter.

– Damien_The_Unbeliever
Nov 15 '18 at 17:39













You are right that it's wrong to expect it to know run time types, but that's what I'm trying to get around. Where would I use dynamic exactly?

– greedyLump
Nov 15 '18 at 17:56





You are right that it's wrong to expect it to know run time types, but that's what I'm trying to get around. Where would I use dynamic exactly?

– greedyLump
Nov 15 '18 at 17:56












2 Answers
2






active

oldest

votes


















0














You are casting the type to the base class. So when you use in with Dapper it sees TypeBase. This is a problem with inheritance. Using a interface might help you solve the problem.






share|improve this answer






























    0














    Here's what ended up working: I made an overload for my FindByID<T> method where I pass b.GetType.ToString() and this gives the correct subclass. In the overload I instantiate one of these and use reflection to pass it as a type parameter to the Dapper extension method.



     public virtual T FindByID<T>(T typeInstance, long id, string typeName) where T : TypeBase

    Assembly asm = Assembly.GetCallingAssembly();
    var item = asm.CreateInstance(typeName);

    using (IDbConnection cn = Connection)

    MethodInfo getInfo = typeof(SqlMapperExtensions).GetMethod("Get");
    MethodInfo getGeneric = getInfo.MakeGenericMethod(item.GetType());
    item = getGeneric.Invoke(cn, new object cn,id,null,null );


    return (T)item;



    This works though I would have like to avoid reflection if I could.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53324767%2fc-sharp-type-parameter-only-reads-as-base-class%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      You are casting the type to the base class. So when you use in with Dapper it sees TypeBase. This is a problem with inheritance. Using a interface might help you solve the problem.






      share|improve this answer



























        0














        You are casting the type to the base class. So when you use in with Dapper it sees TypeBase. This is a problem with inheritance. Using a interface might help you solve the problem.






        share|improve this answer

























          0












          0








          0







          You are casting the type to the base class. So when you use in with Dapper it sees TypeBase. This is a problem with inheritance. Using a interface might help you solve the problem.






          share|improve this answer













          You are casting the type to the base class. So when you use in with Dapper it sees TypeBase. This is a problem with inheritance. Using a interface might help you solve the problem.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 15 '18 at 18:03









          Clayton HarbichClayton Harbich

          3021614




          3021614























              0














              Here's what ended up working: I made an overload for my FindByID<T> method where I pass b.GetType.ToString() and this gives the correct subclass. In the overload I instantiate one of these and use reflection to pass it as a type parameter to the Dapper extension method.



               public virtual T FindByID<T>(T typeInstance, long id, string typeName) where T : TypeBase

              Assembly asm = Assembly.GetCallingAssembly();
              var item = asm.CreateInstance(typeName);

              using (IDbConnection cn = Connection)

              MethodInfo getInfo = typeof(SqlMapperExtensions).GetMethod("Get");
              MethodInfo getGeneric = getInfo.MakeGenericMethod(item.GetType());
              item = getGeneric.Invoke(cn, new object cn,id,null,null );


              return (T)item;



              This works though I would have like to avoid reflection if I could.






              share|improve this answer



























                0














                Here's what ended up working: I made an overload for my FindByID<T> method where I pass b.GetType.ToString() and this gives the correct subclass. In the overload I instantiate one of these and use reflection to pass it as a type parameter to the Dapper extension method.



                 public virtual T FindByID<T>(T typeInstance, long id, string typeName) where T : TypeBase

                Assembly asm = Assembly.GetCallingAssembly();
                var item = asm.CreateInstance(typeName);

                using (IDbConnection cn = Connection)

                MethodInfo getInfo = typeof(SqlMapperExtensions).GetMethod("Get");
                MethodInfo getGeneric = getInfo.MakeGenericMethod(item.GetType());
                item = getGeneric.Invoke(cn, new object cn,id,null,null );


                return (T)item;



                This works though I would have like to avoid reflection if I could.






                share|improve this answer

























                  0












                  0








                  0







                  Here's what ended up working: I made an overload for my FindByID<T> method where I pass b.GetType.ToString() and this gives the correct subclass. In the overload I instantiate one of these and use reflection to pass it as a type parameter to the Dapper extension method.



                   public virtual T FindByID<T>(T typeInstance, long id, string typeName) where T : TypeBase

                  Assembly asm = Assembly.GetCallingAssembly();
                  var item = asm.CreateInstance(typeName);

                  using (IDbConnection cn = Connection)

                  MethodInfo getInfo = typeof(SqlMapperExtensions).GetMethod("Get");
                  MethodInfo getGeneric = getInfo.MakeGenericMethod(item.GetType());
                  item = getGeneric.Invoke(cn, new object cn,id,null,null );


                  return (T)item;



                  This works though I would have like to avoid reflection if I could.






                  share|improve this answer













                  Here's what ended up working: I made an overload for my FindByID<T> method where I pass b.GetType.ToString() and this gives the correct subclass. In the overload I instantiate one of these and use reflection to pass it as a type parameter to the Dapper extension method.



                   public virtual T FindByID<T>(T typeInstance, long id, string typeName) where T : TypeBase

                  Assembly asm = Assembly.GetCallingAssembly();
                  var item = asm.CreateInstance(typeName);

                  using (IDbConnection cn = Connection)

                  MethodInfo getInfo = typeof(SqlMapperExtensions).GetMethod("Get");
                  MethodInfo getGeneric = getInfo.MakeGenericMethod(item.GetType());
                  item = getGeneric.Invoke(cn, new object cn,id,null,null );


                  return (T)item;



                  This works though I would have like to avoid reflection if I could.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 17 '18 at 17:02









                  greedyLumpgreedyLump

                  40111




                  40111



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53324767%2fc-sharp-type-parameter-only-reads-as-base-class%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Use pre created SQLite database for Android project in kotlin

                      Darth Vader #20

                      Ondo