简体   繁体   中英

Passing in a “TYPE” to a Generic_Interface type Property

Scratching my bald patch....I have a generic Interface

interface IGenericInterface<T>
{
    T GenericTypeProperty {get; set;}
    void PerformService(); 
}

I have server classes that implement the generic interface and do some stuff

public class ServeRich : IGenericInterface<RichPeople>
{
    RichPeople GenericTypeProperty {get; set;}
    void PerformService() { //Serving the rich } 
}

public class ServePoor : IGenericInterface<PoorPeople>
{
    PoorPeople GenericTypeProperty {get; set;}
    void PerformService() { //Serving the Poor }
}

Then I have a Service class as follows that I want to invoke and assign one of the server classes to and invoke PerformService()

public class ServeThem
{
    //This is where I am trying to figure out how to do this
    IGenericInterface<T<-??> Server {get; set;}

}

I want to eventually create the Service class and invoke the perform service method on Server....something like this

main()
{
    ServeThem service= new ServeThem();
    service.Server = new ServePoor(); //This will be resolved by Ninject
    service.Server.PerformService();
}

My problem is in IGenericInterface<T<-??> Server {get; set;} IGenericInterface<T<-??> Server {get; set;} . I am trying to figure out how to declare Server property as a generic interface type that can be assigned an object of a class that implements that interface of a particular type. It seems that for declaring IGenericInterface<type> , an actual concrete type has to be mentioned. I tried adding a passedInType property and using typeof(passedInType) but that throws an exception.

How would I declare a property as a generic interface type? Is this even possible.

It seems that you don't use the GenericTypeProperty in your service, so you can move the PerformService method to a non-generic interface and use this interface in the Service class

interface INonGenericInterface
{
    void PerformService(); 
}

interface IGenericInterface<T>: INonGenericInterface
{
    T GenericTypeProperty {get; set;}
}

public class ServeThem
{
    INonGenericInterface Server {get; set;}
}

You're looking for covariance .

// T is covariant (i.e. the "out" keyword)
public interface IGenericInterface<out T>
{
    // Check that I removed the setter. T wouldn't be covariantly valid
    // if it could be set... 
    // BTW, this doesn't prevent an implementation to provide a setter.
    T GenericTypeProperty { get; }
    void PerformService(); 
}

Now turn your ServeThem class to declare the whole property as IGenericInterface<object> :

public class ServeThem
{
    //This is where I am trying to figure out how to do this
    IGenericInterface<object> Server {get; set;}
}

If making read-only the GenericTypeProperty property isn't an option, then this approach won't work for you. Anyway, most of the times you can take advantage of variance replacing a setter with a constructor parameter:

public class ServeRich : IGenericInterface<RichPeople>
{
    private readonly RichPeople _people;

    public ServerRich(RichPeople people)
    {
        _people = people;
    }

    // C# 6 expression-bodied read-only property
    public RichPeople GenericTypeProperty => _people;
    public void PerformService() { //Serving the rich } 
}

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