Create factory that will return object of generic abstract type in .net core












0














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.










share|improve this question






















  • 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










  • Related: Why do I have to cast twice?
    – John Wu
    Nov 20 at 22:16
















0














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.










share|improve this question






















  • 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










  • Related: Why do I have to cast twice?
    – John Wu
    Nov 20 at 22:16














0












0








0







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.










share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 at 21:54









Tosis

318




318












  • 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










  • 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










  • 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












1 Answer
1






active

oldest

votes


















0














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;
}





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%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









    0














    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;
    }





    share|improve this answer




























      0














      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;
      }





      share|improve this answer


























        0












        0








        0






        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;
        }





        share|improve this answer














        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;
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 21 at 11:24

























        answered Nov 21 at 11:07









        matt_lethargic

        2,02011225




        2,02011225






























            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.





            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.




            draft saved


            draft discarded














            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





















































            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

            404 Error Contact Form 7 ajax form submitting

            How to know if a Active Directory user can login interactively

            TypeError: fit_transform() missing 1 required positional argument: 'X'