I have few classes and interfaces in my 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; }
}
I have a .dll library with public classes:
public class ConfigPage : Page<User>
{
}
public class User : IUser
{
public string Name { get; set; }
}
public class Settings : SettingsBase<User>
{
private int _additionalSetting;
}
I want to check if .dll has ConfigPage class, derivied from 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));
Ok, everything is good, but finally my question is:
How to get access to SettingsBase Settings property?
Why this returning null? :
Activator.CreateInstance(type) as Page<IUser> // type is Page<User>, User implement IUser
The reason of null
cast-result is a fact, that generic classes are invariant - you cannot assign an instance of MyClass<Base>
to a variable of type MyClass<Derived>
or vice versa.
I suggest you to update your interfaces with the interfaces-covariance :
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> {
// ...
}
Usage:
IPage<IUser> page = Activator.CreateInstance(typeof(ConfigPage)) as IPage<IUser>;
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.