Returning the generic type of a given interface in C #

Suppose I have the following setup.

Interface IDALModel {}

      

Various classes implement this interface like this ...

class AddressModel : IDALModel 
{
    public int AddressId {get;set;}
    public string Address {get;set;}
}

class AccountModel : IDALModel
{
    public int AccountId {get;set;}
    public string Name {get;set;}
}

class TenantModel : IDALModel
{
    public int TenantId {get;set;}
    public KeyedCollection<int, AddressModel> Addresses {get;set;}
}

      

in another class, I have a method that should return an instance of the class in a generic way.

class SomeClass
{
    internal DataFieldBuilder<IDALModel> Embed<T>(Expression<Func<T, object>> embed, string alias = "")
    {
        PropertyInfo propertyInfo = GetPropertyInfo(embed);
        Type type = propertyInfo.PropertyType.GenericTypeArguments[1];
        DataFieldBuilder<IDALModel> returnObject = new DataFieldBuilder<type>();
    }

    private PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> field)
    {
        PropertyInfo propertyInfo;
        if (field.Body is UnaryExpression)
        {
            propertyInfo = ((MemberExpression)((UnaryExpression)field.Body).Operand).Member as PropertyInfo;
        }
        else
        {
            propertyInfo = ((MemberExpression)field.Body).Member as PropertyInfo;
        }

        return propertyInfo;
    }
}

      

The method Embed

is called from elsewhere as such

DataFieldBuilder<IDALModel> Addresses = test.Embed<TenantModel>(t => t.Addresses);

      

What I am trying to do in the embed method is to extract the base type AddressModel

from the property TenantModel.Addresses

and instantiateDataFieldBuilder<AddressModel>

It doesn't work on line

DataFieldBuilder<IDALModel> returnObject = new DataFieldBuilder<type>();

      

with the message "Unable to implicitly convert the type DataFieldBuilder<AddressModel>

toDataFieldBuilder<IDALModel>

I was hoping that since the IDALModel interface is implemented by AddressModel it will work. Not sure what I'm missing here.

For testing purposes, I even tried to hardcode some examples like

DataFieldBuilder<IDALModel> returnObject = new DataFieldBuilder<AddressModel>();

      

and this gives the same error as well.

+3


source to share


2 answers


You can use a generic method definition and enforce an interface constraint on it:



class SomeClass
{
    public DataFieldBuilder<T> Embed<T>() where T: IDALModel
    {
        var returnObject = new DataFieldBuilder<T>();
        return returnObject;
    }
}

      

+5


source


You want covariance:



public IDataFieldBuilder<IDALModel> Embed<T>() where T : IDALModel
{
    IDataFieldBuilder<IDALModel> returnObject = (IDataFieldBuilder<IDALModel>)new DataFieldBuilder<T>();
    return returnObject;
}

interface IDALModel {}

class AddressModel : IDALModel 
{
    public int AddressId {get;set;}
    public string Address {get;set;}
}

class AccountModel : IDALModel
{
    public int AccountId {get;set;}
    public string Name {get;set;}
}

class DataFieldBuilder<T> : IDataFieldBuilder<T>
{

}

interface IDataFieldBuilder<out T>
{

}

      

0


source







All Articles