C#创建从泛型类型

时间:2016-04-20 10:40:49

标签: c# generics dll casting

我的SDK中有很少的类和接口:

    public interface IUser
    {
        string Name { get; set; }
    }

    public abstract class SettingsBase<TUser> where TUser : IUser
    {
        public ObservableCollection<TUser> Users { get; set; }
    }

    public abstract class Page<TUser> where TUser : IUser
    {
        public SettingsBase<TUser> Settings { get; set; }
    }

我有一个带公共类的.dll库:

public class ConfigPage : Page<User> 
{

}

public class User : IUser
{
    public string Name { get; set; }
}

public class Settings : SettingsBase<User>
{
    private int _additionalSetting;
}

我想检查.dll是否有ConfigPage类,派生自Page:

var dll = Assembly.LoadFrom(@"libraryName.dll");
var type = dll.GetExportedTypes().FirstOrDefault(t => t.Name == "ConfigPage"); // the type is Page<User>
var isIUser = type.BaseType.GetGenericArguments()[0].GetInterfaces().Contains(typeof(IUser));

好的,一切都很好,但最后我的问题是:

如何访问SettingsBase设置属性?

为什么返回null? :

Activator.CreateInstance(type) as Page<IUser>    // type is Page<User>, User implement IUser

1 个答案:

答案 0 :(得分:2)

null强制转换结果的原因是,泛型类不变 - 您无法将MyClass<Base>的实例分配给{{1}类型的变量反之亦然。

我建议您使用interfaces-covariance更新界面:

MyClass<Derived>

用法:

public interface IUser {
    string Name { get; set; }
}
public interface ISettings<out TUser>
    where TUser : IUser {
    IEnumerable<TUser> Users { get; }
}
public interface IPage<out TUser>
    where TUser : IUser {
    ISettings<TUser> Settings { get; }
}

// Abstract implementation
public abstract class SettingsBase<TUser> : ISettings<TUser
    where TUser : IUser {
    public SettingsBase() {
        Users = new ObservableCollection<TUser>();
    }
    public IEnumerable<TUser> Users { get; private set; }
}
public abstract class Page<TUser> : IPage<TUser>
    where TUser : IUser {
    public Page() {
        Settings = CreateSettings();
    }
    public ISettings<TUser> Settings { get; private set; }
    //
    protected abstract ISettings<TUser> CreateSettings();
}
// Real implementation
public class ConfigPage : Page<User> {
    protected override ISettings<User> CreateSettings() {
        return new Settings();
    }
}
public class User : IUser {
    public string Name { get; set; }
}
public class Settings : SettingsBase<User> {
    // ...
}