简体   繁体   中英

Can I cast from an interface to a concrete type with another interface implementation

I should start by saying that I am very much a noobie with interfaces so this might be a really dumb question. Also apologies if my Title is unclear - matches the state of my mind!

I do understand the principles behind interfaces and I am want to use them here both to support unit testing and also decoupling via a DI Framework in what is horribly messy and un-testable legacy code.

I have an inteface called IDatHandler. It has a List<> property called Items. The concrete implementations should return a concrete type of IDatContainer. There are some methods of course but I have left them out

public interface IDatHandler
{
    ....

   List<IDatContainer> Items
    {
        get; set;
    }

}

This is a concrete implementation:

public class ADEColorHandler : IDatHandler
    {
      ....

        public List<ADEColor> Items
        {
            get; set;

        }

    }
}

ADEColor implements IDatContainer. The concrete implementation fails unless I replace ADEColor with IDatContainer .

Is there a way to get Items returned as a list of type ADEColor or am I just breaking the rules?

I should have said that this app is currently using NET 3.5

=========>>> The Answer - thanks Charleh!

The IDatHandler Interface

public interface IDatHandler<T> where T : IDatContainer
{
    ....

   List<IDatContainer> Items
    {
        get; set;
    }

}

The concrete Class:

public class ADEColorHandler : IDatHandler<ADEColor>
        {
          ....

            public List<ADEColor> Items
            {
                get; set;

            }

        }
    }

My units tests on ADEColorHandler Assert against this list and pass.

You could go this route:

public interface IDatHandler
{
    // Any common interface stuff
}

public interface IDatHandler<T> : IDatHandler
    where T : IDatContainer
{
    // Any generics
    List<T> Items;
}

public class ADEColorHandler : IDatHandler<ADEColor>
{
  ....

    public List<ADEColor> Items
    {
        get; set;

    }

}

This does mean you need to do some casting at the other end though since if you just pass around IDatHandler instances, you need to know the generic type before you can query Items

What are you trying to achieve? That might help determine what you can use...

Alternatively you could use IEnumerable in your original interface implementation - do you need to know the concrete type of the collection at design time or can you get away with casting?

Edit: added the constraint above

Just trying to get my head round this because using the above interface will work to a certain degree but my assumption is that you want to loop through these to process them etc - I'm wondering if this would work (need to check)

List<IDatHandler<IDatContainer>> someList = new List<IDatHandler<IDatContainer>>();
someList.Add((IDatHandler<IDatContainer>)new ADEColorHandler());           

Then you could enumerate the list... going to just check to see if this works.

Edit: nope, didn't work since the generic type is actually different at runtime. I'll have a mess around - I enjoy trying to work out what you can and can't do with generics!

Edit:

Ok so the best one is probably:

    public interface IDatHandler<T> : IDatHandler
        where T : IDatContainer
    {
        List<T> Items { get; set; }
    }

    public class ADEColorHandler : IDatHandler<IDatContainer>
    {
        public List<IDatContainer> Items
        {
            get;
            set;

        }
    }

Which means you can do:

var items = new List<IDatHandler<IDatContainer>>();
items.Add(new ADEColorHandler());      

then you can enumerate and get Items from each IDatHandler and query each IDatContainer . Of course you are hidden from the concrete types but I assume you have an interface on the containers to try and abstract those implementation details. This should be fine

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM