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;
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
add a comment |
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
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 usedynamic
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
add a comment |
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
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
c# generics dapper-contrib
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 usedynamic
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
add a comment |
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 usedynamic
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
add a comment |
2 Answers
2
active
oldest
votes
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.
add a comment |
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.
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 15 '18 at 18:03
Clayton HarbichClayton Harbich
3021614
3021614
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 17 '18 at 17:02
greedyLumpgreedyLump
40111
40111
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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