[英]define a generic property in non-generic base class
I dont think what I am trying to do is possible;我不认为我想做的是可能的; is there a way to actually make this work?有没有办法真正使这项工作?
There is a Base
class from which a variety of different classes are derived.有一个Base
class,从中派生出各种不同的类。 Derived classes can be generic or not;派生类可以是通用的,也可以不是; instances of the derived classes are added to a collection of type Base
in WindowViewModel
.派生类的实例被添加到WindowViewModel
中Base
类型的集合中。 The Base class has a collection of Options
that are accessed by the WindowViewModel
. Base class 有一组Options
可以被WindowViewModel
访问。
The issue is: the IOption
interface declares a return type of Func<object, bool> MyFunc
but the return type of MyFunc
needs to be Func<T, bool>
for the generic class method RunIt()
and for the assignment in MyClass
to work.问题是: IOption
接口声明了Func<object, bool> MyFunc
的返回类型,但MyFunc
的返回类型必须是Func<T, bool>
才能使通用 class 方法RunIt()
和MyClass
中的赋值工作. I could make the IOption
generic, but then the Base
class would need to be generic, and then the WindowViewModel.ViewModels
would also need to be redefined somehow.我可以使IOption
通用,但Base
class 需要通用,然后WindowViewModel.ViewModels
也需要以某种方式重新定义。 I dont want to make the Base generic as introducing generics there just makes everything else a real mess.我不想让 Base 变得通用,因为在那里引入 generics 只会让其他一切变得一团糟。
Question: is there a different way to declare MyFunc
in IOption
without using generics to allow assignment of Func<T,bool>
in MyClass
?问题:是否有不同的方法在IOption
中声明MyFunc
而无需使用 generics 以允许在MyClass
中分配Func<T,bool>
?
public interface IOption
{
public string Description {get; set;}
public Expression<Func<object,bool>> MyFunc { get; set; }
}
public class Option : IOption
{
public string Description {get; set;}
public Expression<Func<object,bool>> MyFunc { get; set; }
}
public abstract class Base
{
public abstract ObservableCollection<Option> Options { get; set; }
public abstract Option SelectedOption { get; set; }
public abstract void RunIt();
}
public class Generic<T> : Base
{
private DBContext _context;
public override ObservableCollection<Option> Options { get; set; }
public override Option SelectedOption { get; set; }
public Generic()
: base()
{
Options = new ObservableCollection<Option>();
}
public override void RunIt()
{
var result = _context.Set<T>().Where(SelectedOption?.MyFunc);
// process result
}
}
public class MyClass : Generic<MyType>
{
public MyClass
: base()
{
Func<MyType,bool> expression = t => t.MyDescription = "Hello World";
Options.Add(new Option("Hi", expression)); // fail to compile type mismatch
SelectedOption = Options.First();
}
}
public class Special : Base
{
// do something else
}
public class WindowViewModel
{
public WindowViewModel ()
{
MyViewModels = new ObservableCollection<Base>();
MyViewModels.Add(new Special());
MyViewModels.Add(new MyClass());
}
public ObservableCollection<Base> MyViewModels {get; set;}
public Base SelectedViewModel { get; set; }
public void DoRunIt()
{
SelectedViewModel.RunIt();
}
}
one of the things I did try that compiles but throws runtime exception when used, is我确实尝试编译但在使用时抛出运行时异常的事情之一是
Func<MyType,bool> expression = t => t.MyDescription = "Hello World";
MyFunc = t => expression((MyType)t);
There is a way to do this.有一种方法可以做到这一点。 It uses the ability for all delegates ( Func<MyType, bool>
is a delegate) to be cast to Delegate
.它使用将所有委托( Func<MyType, bool>
是委托)转换为Delegate
的能力。
You'd change IOption
and Option
to this:您将IOption
和Option
更改为此:
public interface IOption
{
public string Description { get; set; }
Func<T, bool> GetMyFunc<T>();
}
public class Option : IOption
{
string description;
private Delegate expression;
public Option(string description, Delegate expression)
{
this.description = description;
this.expression = expression;
}
public string Description { get; set; }
public Func<T, bool> GetMyFunc<T>() => (Func<T, bool>)this.expression;
}
Then MyClass
works as expected (except for the other syntax error in your code).然后MyClass
按预期工作(代码中的其他语法错误除外)。
You then just need to change RunIt
on Generic<T>
to this:然后,您只需将Generic<T>
上的RunIt
更改为:
public override void RunIt()
{
var result = _context.Set<T>().Where(SelectedOption?.GetMyFunc<T>());
// process result
}
Question: is there a different way to declare MyFunc in IOption without using generics to allow assignment of Func<T,bool> in MyClass?问题:是否有不同的方法在 IOption 中声明 MyFunc 而无需使用 generics 以允许在 MyClass 中分配 Func<T,bool>?
No, I don't believe that is possible.不,我不认为这是可能的。 You can have generic methods in a non generic type, though.不过,您可以在非泛型类型中使用泛型方法。
However, there is an option that might work for you.但是,有一个选项可能适合您。 You state你 state
I dont want to make the Base generic as introducing generics there just makes everything else a real mess.我不想让 Base 变得通用,因为在那里引入 generics 只会让其他一切变得一团糟。
How about having both?两者兼得怎么样?
public abstract class Base<T>
{
public abstract ObservableCollection<Option<T>> Options { get; set; }
public abstract Option<T> SelectedOption { get; set; }
public abstract void RunIt();
}
public abstract class Base : Base<object> { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.