6

我正在寻找方法来提高我正在开发的应用程序中某些代码的一致性、简洁性和可读性。起始代码如下所示:

context.GetGraphType<Bar>().Subscribe<Fizz>(
     (instance, evt) => evt.Execute((Bar)instance.Instance)
);

与上面类似,有许多几乎相同的代码行。我想重写它看起来像这样:

typeof(Bar).SubscribeTo<Fizz>(context);

一方面,这将使我能够利用正式化已经成为非正式公约的机会。另外,我希望它现在可以读到类似“bar subscribes to the fizz event on the given context”,而不是“context 获取 bar 类型并订阅 fizz 然后做一些事情”。我认为流程更好,我问过的同事同意了。

我开始将其作为扩展方法来实现。为了完成上述任务,我想为事件类型使用一个抽象的泛型基类,Fizz所以Event<T>. 这意味着扩展方法的泛型类型参数必须被限制为调用扩展方法的类型。所以,对于上面的例子,Fizz必须是 type Event<Bar>

这可能吗?与此同时,我选择了另一种解决方案,但我仍然很好奇它是否可以实现。也欢迎其他建议。

谢谢!

编辑#1:为了清楚起见,我意识到我可以使用额外的类型参数,但我正在寻找尽可能避免这种情况的方法。

编辑#2:我认为我将对接受的答案稍作改动,因为它与我的场景不匹配 100%。底线是可以使用通用静态类代替 Type 的扩展方法来实现我的目标。谢谢dss539!

更新代码(可能有错别字,因为我是在即时执行此操作):

public class Bar { }

public class Event<TSubscriber>
{
    public abstract void Execute(TSubscriber source);
}

public class Fizz : Event<Bar>
{
    public override void Execute(Bar bar)
    {
        // respond to event
    }
}

public class Context { }

public static class ForType<TSubscriber>
{
    public static void SubscribeTo<TEvent>(Context context)
        where TEvent : Event<TSubscriber>
    {
        context.GetType<TSubscriber>().Subscribe<TEvent>(
            (evt, args) => evt.Execute((TSubscriber)args.Source));
    }
}

public static void Run()
{
    ForType<Bar>.SubscribeTo<Fizz>(context);
}
4

3 回答 3

7

这并不完全像你问的那样,但也许就足够了。

internal class Program
{
    static void Main(string[] args)
    {
        var fizzHandler = new Fizz();
        var context = new Context();
        Handle<Bar>.With(fizzHandler, context);
    }
}
public class Bar { }
public class Event<T> { }
public class Fizz : Event<Bar> { }
public class Context { };
public static class Handle<T>
{
    public static void With(Event<T> e, Context c)
    {
        //do your stuff
    }
}
于 2010-07-01T15:59:14.027 回答
4

为什么不做一些更符合规范的事情,您可以使用通用约束来强制执行规则:

 public static class SubscriptionManager
 {
     public static void SubsribeTo<TSub,TEvent>( Context context )
         where TEvent : Event<TSub>
     {
        /// you code...
     }
 }

调用看起来像:

 SubscriptionManager.SubsribeTo<Bar,Fizz>( context );

该约束where TEvent : Event<TSub>确保了您想要的事件和订阅类型之间的关系。在我的书中,它也比类上的扩展方法更可取Type——因为这往往会使智能感知变得混乱。Type在许多情况下使用,并且在 Intellisense 的所有实例上出现虚假方法Type往往会造成混淆。对于图书馆的消费者来说,这是“订阅”的方式也是不明显的——除非他们实际上已经看到了它的代码示例。

于 2010-06-25T14:54:49.763 回答
0

您可能可以接近扩展System.Type(拥有typeof(T).)并向上下文添加(扩展)方法,将 .NET 类型转换为您的内部类型表示(与返回相同GetGraphType)。

static class Ext {

    public static TypeofTypeofBar GetGraphTypeFromDotNetType(this Context ctx, Type t) {
       return __something(t);
    }

    public static void SubscribeTo<F, E>(this Type type, Context ctx, E e)
        where E: Event<T> {
        context.GetGraphTypeFromDotNetType(type).Subscribe<F>(a);
    }

}

...

typeof(Bar).SubscribeTo(context, action);
于 2010-06-25T14:56:26.330 回答