C#Generics,Base Classes和EventArgs,MVP,DI

时间:2016-01-22 14:28:46

标签: c# events generics

我知道我可能通过尝试这个来打破一些规则,但我试图用EventArgs建立一个通用的基类。起初,我认为这很简单。使用简单的遗留(确保视图仅由演示者更新)MVP模式方法,我想做以下事情。顺便说一句,我还有一些DI(城堡)也在继续,但它并不相关。

我有一个基本演示者类

 public abstract class PresenterBase<K, T> where K : IView, IPresenter<K, T>
 {
    public event EventHandler<T> StartSomethingEvent;
    public K _view { get; set; }

    public PresenterBase(K view)
    {   
        _view = view;
        _view.Start += new StartEventHandler(OnStartSomethingEventHandler);
    }

    public virtual void OnStartSomething(T args)
    {
        EventHandler<T> handler = StartSomethingEvent;
        if (handler != null)
        {
            handler(this, args);
        }
    }
 }

和视图基类

public abstract class ViewBase: IView
{
    public abstract void WriteOutput(string message);

    public event StartEventHandler Start;
}

让我们添加一些接口(哦再说一遍) 主讲人:

public interface IPresenter<V, E>
{
    event EventHandler<E> StartSomethingEvent;

    V _view { get; set; }

    void OnStartSomething(E args);
}

查看:

public interface IView
{   
    event StartEventHandler Start;

    void WriteOutput(string message);
}

这些似乎非常直接(我认为)

现在为实际的实现类(这是我遇到困难的东西)

主讲人:

public class ImplementedPresenter : PresenterBase<SomeImplementedView, SomeFancyDancyEventArgs>,
    IImplementedPresenter
{
    public ImplementedPresenter(
        IView view)
        : base(view)
    {
       //Some additional wire ups going on that are out of scope.
    }
}

查看:

public class SomeImplementedView : ViewBase
{
    public static event StartEventHandler Start;

    static void Main(string[] args)
    {
        Resolve();
        OnReady();
    }

    static void Resolve()
    {
        //DI Stuff
        IWindsorContainer container = new WindsorContainer(new XmlInterpreter());
        container.Kernel.Resolver.AddSubResolver(new ListResolver(container.Kernel));

        //Must be resolved before using
        container.Resolve<IImplementedPresenter>();
    }

    static void OnReady()
    {
        StartEventHandler handler = Start;
        if (handler != null)
        {
            handler();
        }
    }

    public override void WriteOutput(string message)
    {
        Console.WriteLine(message);
    }
}

但是,这可能会打破Liskov替换规则。

因为我害怕。

"There is no implicit reference conversion from 'SomeImplementedView' to 
'IPresenter<SomeImplementedView,SomeFancyDancyEventArgs>." Message
呃,这让我以前得到了我,我不记得我做了什么来解决这个问题。经过几天的冲击(重构,重构,重构)和思考&#34;为什么我要经历这种痛苦&#34;,我问自己,&#34;自我&#34;为什么不在StackOverflow问问聪明的人,&#34;任何人都对这个问题有任何建议吗?&#34;

哦,亲切,精彩,聪明,聪明的人,教我。发送仅在此论坛上发现的智慧。

修订: 我简化了代码并使其正常工作(见下文)

public delegate void StartEventHandler();

public class SomeEventArgs : System.EventArgs
{
    private readonly string _somefield;

    public string SomeData { get { return _somefield; } }

    public SomeEventArgs(string somedata)
    {
        _somefield = somedata;
    }
}

public interface IPresenter<V, E>
    where V : IView
{
    event EventHandler<E> StartSomethingEvent;

    V _view { get; set; }

    void OnStartSomething(E args);

}

public abstract class PresenterBase<V, E> : IPresenter<V, E>
    where V : IView
{
    public event EventHandler<E> StartSomethingEvent;

    public V _view { get; set; }

    public PresenterBase(V view)
    {
        _view = view;
        _view.Start += new StartEventHandler(ViewStart_OnStart);
    }

    public void ViewStart_OnStart()
    {
        Process();
    }

    public abstract void Process();

    public void OnStartSomething(E args)
    {
        EventHandler<E> handler = StartSomethingEvent;
        if (handler != null)
        {
            handler(this, args);
        }
    }
}

public class ImplementedPresenter : PresenterBase<IView, SomeEventArgs>
{
    public ImplementedPresenter(IView view)
        : base(view)
    {
        //Some additional wire ups going on that are out of scope.
    }

    public override void Process()
    {
        OnStartSomething("start data");
    }

    public void OnStartSomething(string somedata)
    {
        SomeEventArgs args = new SomeEventArgs(somedata);
        base.OnStartSomething(args);
    }
}

public interface IView
{
    event StartEventHandler Start;

    void WriteOutput(string message);
}

public abstract class ViewBase : IView
{
    public abstract void WriteOutput(string message);

    public event StartEventHandler Start;
}

public class ImplementedView : ViewBase
{
    public static event StartEventHandler Start;

    static void Main(string[] args)
    {
        Resolve();
        OnReady();
    }

    static void Resolve()
    {}

    static void OnReady()
    {
        StartEventHandler handler = Start;
        if (handler != null)
        {
            handler();
        }
    }

    public override void WriteOutput(string message)
    {
        Console.WriteLine(message);
    }
}

2 个答案:

答案 0 :(得分:0)

您明确要求您的班级'SomeImplementedView' 将实现(继承自) - &gt; IPresenter<K, T>

您是通过'where K : IView, IPresenter<K, T>'

执行此操作的

所以你得到这个编译器问题 - 正确..

为了解决这个问题 - 你应该:

public class SomeImplementedView : IView, IPresenter<ClassA, ClassB>{}

或删除/调整您的通用类的约束 - &gt; where ....

答案 1 :(得分:0)

这会编译并可能为您提供构建的工作点:

public interface IView<V, P, T>
    where V : IView<V, P, T>
    where P : IPresenter<V, P, T>
{ }

public interface IPresenter<V, P, T>
    where V : IView<V, P, T>
    where P : IPresenter<V, P, T>
{ }

public abstract class PresenterBase<V, P, T> : IPresenter<V, P, T>
    where V : IView<V, P, T>
    where P : IPresenter<V, P, T>
{ }

public abstract class ViewBase<V, P, T> : IView<V, P, T>
    where V : IView<V, P, T>
    where P : IPresenter<V, P, T>
{ }

public class ImplementedPresenter : PresenterBase<SomeImplementedView, ImplementedPresenter, SomeFancyDancyEventArgs>
{ }

public class SomeImplementedView : ViewBase<SomeImplementedView, ImplementedPresenter, SomeFancyDancyEventArgs>
{ }