1

我有以下情况:

class MyControl<T> : UserControl where T:TClass
{
    public T Field {}
    public event EventHandler<MyEventArgs<T>> MyEvent;
}
class DerControl1 : MyControl<ClassA> {}
class DerControl2 : MyControl<ClassB> {}

我应该如何实现继承以拥有 DerControl1、DerControl2 的基类以访问 MyControl 的接口?

SomeBaseClass control = condition ? DerControl1 :DerControl2;
control.Field = null;
control.Enabled=false;

SomeBaseClass 应该是什么类?

4

4 回答 4

2

定义另一个非泛型接口IMyControl并显式实现它:

public interface IMyControl
{
    public TClass Field { get; set; }
    public bool Enabled { get; set; }
}

class MyControl<T> : UserControl, IMyControl where T:TClass
{
    public T Field { get; set; }
    TClass IMyControl.Field
    {
        get { return this.Field; }
        set { this.Field = (T)value; }
    }
    public event EventHandler<MyEventArgs<T>> MyEvent;
}

您现在可以将派生控件转换为类型IMyControl并访问该Field属性TClass。尝试像其他任何东西一样返回违反了协/逆变(您可以返回 anobject但在这种情况下最好返回 a TClass,因为类型约束已经存在)

于 2013-04-17T10:00:33.393 回答
1

您可以使用UserControl来访问该Enabled字段,但没有定义的通用类型Field。你不能放入Field一个通用的非泛型接口,因为它的类型是泛型的。

从 C# 4.0 开始,您可以使用dynamic以下方式:

dynamic control = condition ? DerControl1 :DerControl2;
control.Field = null;
control.Enabled=false;

这可能会稍微慢一些,但它会编译并执行您想要的操作。

于 2013-04-17T09:45:23.150 回答
0

用例不清楚。如果此代码:

control.Field = null;
control.Enabled=false;

不会被放入泛型方法(或泛型类型的方法)中,而不是您根本不需要泛型:

class MyControl : UserControl where T:TClass
{
    public object Field {}
    public event EventHandler<MyEventArgs> MyEvent;
}

否则,此代码将正常工作。

于 2013-04-17T09:55:20.280 回答
0

使用您自己的问题,您不能只使用界面吗?

public interface IMyControl<T> where T:class
{
    T Field { get; set;}
    event EventHandler<MyEventArgs<T>> MyEvent;
}

public class MyControl<T> : UserControl, IMyControl<T> where T:class
{
    public T Field { get; set;}
    public event EventHandler<MyEventArgs<T>> MyEvent;       
}

然后使用:

// (which equates to IMyControl control = ...)
var control = condition ? new MyControl<ClassA>() : new MyControl<ClassB>();
control.Field = null;
control.Enabled = false;

这为您要使用的每个类型参数节省了多个类,因此鼓励代码重用并遵循多态性 (OOP)。

希望这有帮助!

编辑

好的——所以亚历克斯是对的,我不应该从臀部开火!经过一番调查,这似乎比我想象的要困难得多!所以我开始怀疑你问的是不是正确的方法。现在,是否是你想要的答案,我不知道,但这里是你思考的问题。

基本上,不要使用泛型。在这种情况下,生活真的很艰难!相反,隐藏在接口后面。下面的代码实现了与您在上面尝试的相同,但您现在将字段绑定到“具体”接口。但实际上,你想要这个——你应该知道行为和模式,否则,在我看来,你不知道你的系统应该做什么,因此你的要求有问题。无论如何,召唤结束,这里有一些代码!

public interface IMyClass
{
    int I { get; set; }
    string S { get; set; }
}

public interface IMyControl
{
    IMyClass Field { get; set; }
    event EventHandler<EventArgs> MyEvent;
}

public class MyControl : UserControl, IMyControl
{
    public MyControl(IMyClass field)
    {
        this.Field = field;
    }

    public IMyClass Field { get; set; }

    public event EventHandler<EventArgs> MyEvent;
}

public class MyClass1 : IMyClass
{
    public int I { get; set; }
    public string S { get; set; }

    public override string ToString()
    {
        return "I am a MyClass1!!!";
    }
}

public class MyClass2 : IMyClass
{
    public int I { get; set; }
    public string S { get; set; }

    public override string ToString()
    {
        return "I am a MyClass2!!!";
    }
}

var control = someCondition ? new MyControl(new MyClass1()) : new MyControl(new MyClass2());
于 2013-04-17T10:20:04.723 回答