Create factory that will return object of generic abstract type in .net core
I'm creating code that is using abstract generic class as base. I got a little stuck since I'm try to create factory that will return specific object base on inserted object type.
Lets say that i want to compare to object to check are they are equal or not. In my scenario i want to compare object in way base on that if they are type of IEnumerable
or IList
My code :
Interface :
public interface IObjectComparer<in T>
{
bool Compare(T obj1, T obj2);
}
Base class :
public abstract class ObjectComparerBase<T> : IObjectComparer<T>
{
public abstract bool Compare(T obj1, T obj2);
public void SomeUsefullHelperMethod()
{
}
}
IList
object comparer :
public sealed class ListObjectComparer : ObjectComparerBase<IList>
{
public override bool Compare(IList obj1, IList obj2)
{
throw new NotImplementedException();
}
}
and IEnumerable
object comparer
public sealed class EnumerableObjectComparer : ObjectComparerBase<IEnumerable>
{
public override bool Compare(IEnumerable obj1, IEnumerable obj2)
{
throw new System.NotImplementedException();
}
}
At the end i have my factory that should decide if which comparer i need to use for certain object :
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer = null;
switch (typeof(T))
{
case IEnumerable o:
{
comparer = new EnumerableObjectComparer();
break;
}
case IList o:
{
comparer = new ListObjectComparer();
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
My problem :
In current scenario i cannot use my ComparerRetriever
class because compilator is say that nether ListObjectComparer
nor EnumerableObjectComparer
is not IObjectComparer<T>
type.
My question is why ? My objects are have ObjectComparerBase<T>
class as a parent and this class is implementing IObjectComparer<T>
so in my opinion EnumerableObjectComparer
and ListObjectComparer
should be type of ObjectComparerBase<T>
Probably I'm missing something but at this point I cannot see what.
Can you help me ?
Thanks.
c# generics .net-core
add a comment |
I'm creating code that is using abstract generic class as base. I got a little stuck since I'm try to create factory that will return specific object base on inserted object type.
Lets say that i want to compare to object to check are they are equal or not. In my scenario i want to compare object in way base on that if they are type of IEnumerable
or IList
My code :
Interface :
public interface IObjectComparer<in T>
{
bool Compare(T obj1, T obj2);
}
Base class :
public abstract class ObjectComparerBase<T> : IObjectComparer<T>
{
public abstract bool Compare(T obj1, T obj2);
public void SomeUsefullHelperMethod()
{
}
}
IList
object comparer :
public sealed class ListObjectComparer : ObjectComparerBase<IList>
{
public override bool Compare(IList obj1, IList obj2)
{
throw new NotImplementedException();
}
}
and IEnumerable
object comparer
public sealed class EnumerableObjectComparer : ObjectComparerBase<IEnumerable>
{
public override bool Compare(IEnumerable obj1, IEnumerable obj2)
{
throw new System.NotImplementedException();
}
}
At the end i have my factory that should decide if which comparer i need to use for certain object :
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer = null;
switch (typeof(T))
{
case IEnumerable o:
{
comparer = new EnumerableObjectComparer();
break;
}
case IList o:
{
comparer = new ListObjectComparer();
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
My problem :
In current scenario i cannot use my ComparerRetriever
class because compilator is say that nether ListObjectComparer
nor EnumerableObjectComparer
is not IObjectComparer<T>
type.
My question is why ? My objects are have ObjectComparerBase<T>
class as a parent and this class is implementing IObjectComparer<T>
so in my opinion EnumerableObjectComparer
and ListObjectComparer
should be type of ObjectComparerBase<T>
Probably I'm missing something but at this point I cannot see what.
Can you help me ?
Thanks.
c# generics .net-core
Unfortunately, the compiler doesn't understand the link between the type ofT
, thecase
and your constructed types. The only way to construct and return those, assuming the types really do match, is to doreturn (IObjectComparer<T>)(object)new EnumerableObjectComparer();
(I believe the mid-cast toobject
is necessary but try without)
– Lasse Vågsæther Karlsen
Nov 20 at 22:00
This Cast is Helping in that scenario. I also needed this mid-cast. I think that this is good answer. Maybe code will not look best by this cast but at least i till compile.
– Tosis
Nov 20 at 22:06
Related: Why do I have to cast twice?
– John Wu
Nov 20 at 22:16
add a comment |
I'm creating code that is using abstract generic class as base. I got a little stuck since I'm try to create factory that will return specific object base on inserted object type.
Lets say that i want to compare to object to check are they are equal or not. In my scenario i want to compare object in way base on that if they are type of IEnumerable
or IList
My code :
Interface :
public interface IObjectComparer<in T>
{
bool Compare(T obj1, T obj2);
}
Base class :
public abstract class ObjectComparerBase<T> : IObjectComparer<T>
{
public abstract bool Compare(T obj1, T obj2);
public void SomeUsefullHelperMethod()
{
}
}
IList
object comparer :
public sealed class ListObjectComparer : ObjectComparerBase<IList>
{
public override bool Compare(IList obj1, IList obj2)
{
throw new NotImplementedException();
}
}
and IEnumerable
object comparer
public sealed class EnumerableObjectComparer : ObjectComparerBase<IEnumerable>
{
public override bool Compare(IEnumerable obj1, IEnumerable obj2)
{
throw new System.NotImplementedException();
}
}
At the end i have my factory that should decide if which comparer i need to use for certain object :
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer = null;
switch (typeof(T))
{
case IEnumerable o:
{
comparer = new EnumerableObjectComparer();
break;
}
case IList o:
{
comparer = new ListObjectComparer();
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
My problem :
In current scenario i cannot use my ComparerRetriever
class because compilator is say that nether ListObjectComparer
nor EnumerableObjectComparer
is not IObjectComparer<T>
type.
My question is why ? My objects are have ObjectComparerBase<T>
class as a parent and this class is implementing IObjectComparer<T>
so in my opinion EnumerableObjectComparer
and ListObjectComparer
should be type of ObjectComparerBase<T>
Probably I'm missing something but at this point I cannot see what.
Can you help me ?
Thanks.
c# generics .net-core
I'm creating code that is using abstract generic class as base. I got a little stuck since I'm try to create factory that will return specific object base on inserted object type.
Lets say that i want to compare to object to check are they are equal or not. In my scenario i want to compare object in way base on that if they are type of IEnumerable
or IList
My code :
Interface :
public interface IObjectComparer<in T>
{
bool Compare(T obj1, T obj2);
}
Base class :
public abstract class ObjectComparerBase<T> : IObjectComparer<T>
{
public abstract bool Compare(T obj1, T obj2);
public void SomeUsefullHelperMethod()
{
}
}
IList
object comparer :
public sealed class ListObjectComparer : ObjectComparerBase<IList>
{
public override bool Compare(IList obj1, IList obj2)
{
throw new NotImplementedException();
}
}
and IEnumerable
object comparer
public sealed class EnumerableObjectComparer : ObjectComparerBase<IEnumerable>
{
public override bool Compare(IEnumerable obj1, IEnumerable obj2)
{
throw new System.NotImplementedException();
}
}
At the end i have my factory that should decide if which comparer i need to use for certain object :
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer = null;
switch (typeof(T))
{
case IEnumerable o:
{
comparer = new EnumerableObjectComparer();
break;
}
case IList o:
{
comparer = new ListObjectComparer();
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
My problem :
In current scenario i cannot use my ComparerRetriever
class because compilator is say that nether ListObjectComparer
nor EnumerableObjectComparer
is not IObjectComparer<T>
type.
My question is why ? My objects are have ObjectComparerBase<T>
class as a parent and this class is implementing IObjectComparer<T>
so in my opinion EnumerableObjectComparer
and ListObjectComparer
should be type of ObjectComparerBase<T>
Probably I'm missing something but at this point I cannot see what.
Can you help me ?
Thanks.
c# generics .net-core
c# generics .net-core
asked Nov 20 at 21:54
Tosis
318
318
Unfortunately, the compiler doesn't understand the link between the type ofT
, thecase
and your constructed types. The only way to construct and return those, assuming the types really do match, is to doreturn (IObjectComparer<T>)(object)new EnumerableObjectComparer();
(I believe the mid-cast toobject
is necessary but try without)
– Lasse Vågsæther Karlsen
Nov 20 at 22:00
This Cast is Helping in that scenario. I also needed this mid-cast. I think that this is good answer. Maybe code will not look best by this cast but at least i till compile.
– Tosis
Nov 20 at 22:06
Related: Why do I have to cast twice?
– John Wu
Nov 20 at 22:16
add a comment |
Unfortunately, the compiler doesn't understand the link between the type ofT
, thecase
and your constructed types. The only way to construct and return those, assuming the types really do match, is to doreturn (IObjectComparer<T>)(object)new EnumerableObjectComparer();
(I believe the mid-cast toobject
is necessary but try without)
– Lasse Vågsæther Karlsen
Nov 20 at 22:00
This Cast is Helping in that scenario. I also needed this mid-cast. I think that this is good answer. Maybe code will not look best by this cast but at least i till compile.
– Tosis
Nov 20 at 22:06
Related: Why do I have to cast twice?
– John Wu
Nov 20 at 22:16
Unfortunately, the compiler doesn't understand the link between the type of
T
, the case
and your constructed types. The only way to construct and return those, assuming the types really do match, is to do return (IObjectComparer<T>)(object)new EnumerableObjectComparer();
(I believe the mid-cast to object
is necessary but try without)– Lasse Vågsæther Karlsen
Nov 20 at 22:00
Unfortunately, the compiler doesn't understand the link between the type of
T
, the case
and your constructed types. The only way to construct and return those, assuming the types really do match, is to do return (IObjectComparer<T>)(object)new EnumerableObjectComparer();
(I believe the mid-cast to object
is necessary but try without)– Lasse Vågsæther Karlsen
Nov 20 at 22:00
This Cast is Helping in that scenario. I also needed this mid-cast. I think that this is good answer. Maybe code will not look best by this cast but at least i till compile.
– Tosis
Nov 20 at 22:06
This Cast is Helping in that scenario. I also needed this mid-cast. I think that this is good answer. Maybe code will not look best by this cast but at least i till compile.
– Tosis
Nov 20 at 22:06
Related: Why do I have to cast twice?
– John Wu
Nov 20 at 22:16
Related: Why do I have to cast twice?
– John Wu
Nov 20 at 22:16
add a comment |
1 Answer
1
active
oldest
votes
So this works and returns the classes as expected. You will have to put IList first because IList implements IEnumerable and if IEnumerable is first it will also fall to that case.
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
switch (typeof(T))
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
I do think though that you will always hit the default case as any object you pass to the Retrieve
method as it will have a concrete type and the typeof
will result in that concrete type not the Intreface
For instance when I did my testing I created
class SimpleList : IList
{
... blah
}
and predictably the typeof
call resulted in SimpleList and not IList so it always threw
NotSupportedException("Not Supported Type");
obviously I could be wrong and you could be one step ahead of me so I'll leave my answer there as I believe I've answered the original question
UPDATE
After more testing I'm not sure you can use pattern matching on interfaces, I have since changed my implementation to the below and I still hit the default case.
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
var interf = typeof(T).GetInterfaces().FirstOrDefault();
switch (interf)
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
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%2f53402170%2fcreate-factory-that-will-return-object-of-generic-abstract-type-in-net-core%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
So this works and returns the classes as expected. You will have to put IList first because IList implements IEnumerable and if IEnumerable is first it will also fall to that case.
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
switch (typeof(T))
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
I do think though that you will always hit the default case as any object you pass to the Retrieve
method as it will have a concrete type and the typeof
will result in that concrete type not the Intreface
For instance when I did my testing I created
class SimpleList : IList
{
... blah
}
and predictably the typeof
call resulted in SimpleList and not IList so it always threw
NotSupportedException("Not Supported Type");
obviously I could be wrong and you could be one step ahead of me so I'll leave my answer there as I believe I've answered the original question
UPDATE
After more testing I'm not sure you can use pattern matching on interfaces, I have since changed my implementation to the below and I still hit the default case.
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
var interf = typeof(T).GetInterfaces().FirstOrDefault();
switch (interf)
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
add a comment |
So this works and returns the classes as expected. You will have to put IList first because IList implements IEnumerable and if IEnumerable is first it will also fall to that case.
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
switch (typeof(T))
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
I do think though that you will always hit the default case as any object you pass to the Retrieve
method as it will have a concrete type and the typeof
will result in that concrete type not the Intreface
For instance when I did my testing I created
class SimpleList : IList
{
... blah
}
and predictably the typeof
call resulted in SimpleList and not IList so it always threw
NotSupportedException("Not Supported Type");
obviously I could be wrong and you could be one step ahead of me so I'll leave my answer there as I believe I've answered the original question
UPDATE
After more testing I'm not sure you can use pattern matching on interfaces, I have since changed my implementation to the below and I still hit the default case.
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
var interf = typeof(T).GetInterfaces().FirstOrDefault();
switch (interf)
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
add a comment |
So this works and returns the classes as expected. You will have to put IList first because IList implements IEnumerable and if IEnumerable is first it will also fall to that case.
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
switch (typeof(T))
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
I do think though that you will always hit the default case as any object you pass to the Retrieve
method as it will have a concrete type and the typeof
will result in that concrete type not the Intreface
For instance when I did my testing I created
class SimpleList : IList
{
... blah
}
and predictably the typeof
call resulted in SimpleList and not IList so it always threw
NotSupportedException("Not Supported Type");
obviously I could be wrong and you could be one step ahead of me so I'll leave my answer there as I believe I've answered the original question
UPDATE
After more testing I'm not sure you can use pattern matching on interfaces, I have since changed my implementation to the below and I still hit the default case.
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
var interf = typeof(T).GetInterfaces().FirstOrDefault();
switch (interf)
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
So this works and returns the classes as expected. You will have to put IList first because IList implements IEnumerable and if IEnumerable is first it will also fall to that case.
public sealed class ComparerRetriever
{
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
switch (typeof(T))
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
}
I do think though that you will always hit the default case as any object you pass to the Retrieve
method as it will have a concrete type and the typeof
will result in that concrete type not the Intreface
For instance when I did my testing I created
class SimpleList : IList
{
... blah
}
and predictably the typeof
call resulted in SimpleList and not IList so it always threw
NotSupportedException("Not Supported Type");
obviously I could be wrong and you could be one step ahead of me so I'll leave my answer there as I believe I've answered the original question
UPDATE
After more testing I'm not sure you can use pattern matching on interfaces, I have since changed my implementation to the below and I still hit the default case.
public static IObjectComparer<T> Retrieve<T>(T obj)
{
IObjectComparer<T> comparer;
var interf = typeof(T).GetInterfaces().FirstOrDefault();
switch (interf)
{
case IList o:
{
comparer = new ListObjectComparer() as IObjectComparer<T>;
break;
}
case IEnumerable o:
{
comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
break;
}
default:
throw new NotSupportedException("Not Supported Type");
}
return comparer;
}
edited Nov 21 at 11:24
answered Nov 21 at 11:07
matt_lethargic
2,02011225
2,02011225
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53402170%2fcreate-factory-that-will-return-object-of-generic-abstract-type-in-net-core%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
Unfortunately, the compiler doesn't understand the link between the type of
T
, thecase
and your constructed types. The only way to construct and return those, assuming the types really do match, is to doreturn (IObjectComparer<T>)(object)new EnumerableObjectComparer();
(I believe the mid-cast toobject
is necessary but try without)– Lasse Vågsæther Karlsen
Nov 20 at 22:00
This Cast is Helping in that scenario. I also needed this mid-cast. I think that this is good answer. Maybe code will not look best by this cast but at least i till compile.
– Tosis
Nov 20 at 22:06
Related: Why do I have to cast twice?
– John Wu
Nov 20 at 22:16