繁体   English   中英

具有泛型类型参数的类型的C#扩展方法

[英]C# Extension Method on Type With Generic Type Argument

我正在研究如何提高我正在处理的应用程序中某些代码的一致性,简洁性和可读性。 起始代码看起来像这样:

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

如上所述,有许多几乎相同的代码行。 我想重写它看起来像这样:

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

首先,这将使我能够利用已经成为非正式会议的形式化。 此外,我希望它现在会读取类似“bar在订阅上下文中订阅fizz事件”,而不是“上下文获取条形码并订阅fizz然后做一些事情。”我认为流程是更好,我询问同事的同事。

我开始将其作为扩展方法实现。 为了实现上述目的,我想为事件类型使用抽象通用基类,因此Fizz将是Event<T> 这意味着扩展方法的泛型类型参数必须被约束为调用扩展方法的类型。 因此,对于上面的示例, Fizz必须是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);
}

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

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
    }
}

为什么不做一些更具体味的事情,你可以使用通用约束来强制执行规则:

 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 ,并且在所有Type实例上在Intellisense中出现虚假方法往往会造成混淆。 对于图书馆的消费者而言,这是“订阅”的方式也是不明显的 - 除非他们实际上已经看到了它的代码示例。

您可以近距离扩展System.Type (具有typeof(T). )并向上下文添加(扩展)方法,将.NET类型转换为内部类型表示(与GetGraphType返回的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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM