Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时决定调用哪个类_C#_.net Core - Fatal编程技术网

C# 在运行时决定调用哪个类

C# 在运行时决定调用哪个类,c#,.net-core,C#,.net Core,在我的方法中,我必须决定如何处理传入的数据。这些对象包含一个字符串,该字符串定义了如何处理它们 目前我有以下课程: interface INotifier{ string Name { get; } Task SendNotification(Notification); } public class WhatsappNotifier : INotifier{ public string Name => "whatsapp"; public async T

在我的方法中,我必须决定如何处理传入的数据。这些对象包含一个字符串,该字符串定义了如何处理它们

目前我有以下课程:

interface INotifier{
    string Name { get; }
    Task SendNotification(Notification);
}

public class WhatsappNotifier : INotifier{
    public string Name => "whatsapp";
    public async Task SendNotification(Notification notification){
        //Handle notification
    }
}

public class EmailNotifier : INotifier{
    public string Name => "email";
    public async Task SendNotification(Notification notification){
        //Handle notification
    }
}


public class NotificationCoordinator{
    private readonly INotifier[] _notifiers;
    public NotificationCoordinator(EmailNotifier emailNotifier, WhatsappNotifier whatsappNotifier){
        _notifiers = new INotifier[]
        {
            emailNotifier,
            whatsappNotifier
        };
    }

    public async Task HandleNotifications(Notification[] notifications){
        INotifier notifier = null;
        foreach(Notification notification in notifications){
            notifier = _notifiers.Where(n => n.Name == notification.Type).FirstOrDefault();
            if(notifier != null)
                await notifier.SendNotification(notification);

        }
    }
}

根据通知的type属性,它选择正确的通知程序类来处理通知业务。这很好,但我从一位同事那里得到了一些反馈,认为这可以用更好的方式来实现,但我不确定如何实现。是否有适合此场景的设计模式?

在您的示例中,您使用的是“策略”模式。无论如何,它没有完全正确地实现,因为您的类
NotificationCoordinator
违反了单一责任原则。在这种情况下,您应该将“应该使用哪个INotifier”的决策过程委托给单独的类,例如:

public class NotificationStrategy : INotificationStrategy
{
    private readonly IEmailNotifier _emailNotifier;
    private readonly IWhatsappNotifier _whatsappNotifier;

    public NotificationStrategy(IEmailNotifier emailNotifier, IWhatsappNotifier whatsappNotifier)
    {
        _emailNotifier = emailNotifier;
        _whatsappNotifier = whatsappNotifier;
    }

    public INotifier GetNotifier(Notification notification)
    {
        // Notifies selection logic HERE
    }
}

现在,您必须更改
NotificationCoordinator
CTOR,并使用
NotificationStrategy
作为依赖项。接下来在
HandleNotifications
中,使用
GetNotifier
获取正确的通知程序。当然,您应该避免使用具体的类,例如,
通知
——您应该用一些抽象来代替它。

我不会说这个解决方案更好,但至少是不同的,它基于依赖注入:

public class Notification
{
    public string Type { get; set; }
    public string Body { get; set; }
    public string Recipients { get; set; }
}

public interface INotifier
{
    Task SendAsync(Notification notification);
}

public class WhatsAppNotifier : INotifier
{
    public Task SendAsync(Notification notification)
    {
        throw new NotImplementedException();
    }
}

public class EmailNotifier : INotifier
{
    public Task SendAsync(Notification notification)
    {
        throw new NotImplementedException();
    }
}

public class NotifierFactory
{
    private readonly IServiceProvider serviceProvider;
    public NotifierFactory(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }
    public INotifier Get(string name)
    {
        return serviceProvider.GetNotifier(name);
    }
}

public class GeneralNotifier : INotifier
{

    private readonly NotifierFactory notifierFactory;
    public GeneralNotifier(NotifierFactory notifierFactory)
    {
        this.notifierFactory = notifierFactory;
    }

    public Task SendAsync(Notification notification)
    {
        var notifier = notifierFactory.Get(notification.Type);
        return notifier.SendAsync(notification);
    }
}

public class BulkNotifier
{
    private readonly INotifier notifier;

    public BulkNotifier(INotifier notifier)
    {
        this.notifier = notifier;
    }

    public async Task SendNotificationsAsync(IEnumerable<Notification> notifications)
    {
        foreach (var notification in notifications)
        {
            await notifier.SendAsync(notification);
        }
    }
}

public static class DependencyInjection
{
    private static Dictionary<string, Type> notifierByName = new Dictionary<string, Type>();

    private static IServiceCollection AddScopedNotifier<T>(this IServiceCollection services, string name) where T: class, INotifier 
    {
        notifierByName[name] = typeof(T);
        return services.AddScoped<T>();
    }

    public static INotifier GetNotifier(this IServiceProvider serviceProvider, string name)
    {
        if (!notifierByName.TryGetValue(name, out Type notifierType))
        {
            throw new KeyNotFoundException($"{name} notifier is not registered with the depencency injection container. Please call IServiceCollection.AddNotifier");

        }
        return (INotifier)serviceProvider.GetRequiredService(notifierType);
    }

    public static IServiceCollection AddNotifiers(this IServiceCollection services)
    {
        return services
            .AddScopedNotifier<WhatsAppNotifier>("whatsapp")
            .AddScopedNotifier<EmailNotifier>("email")
            .AddScoped(serviceProvider => new NotifierFactory(serviceProvider))
            .AddScoped<INotifier, GeneralNotifier>()
            .AddScoped<BulkNotifier>();
    }

}

“那么你的服务和控制器就可以依赖于
BulkNotifier
INotifier

问问你的同事,”他这样说。对你同事来说,那是一个毫无用处的评论。有很多不同的方法可以做到这一点。使用
字典
,使用访客模式。。。有些可能执行得更好,有些可能比其他更可读,有些可能更易于维护。。。这取决于他对“更好”的定义。说得对。这家伙很忙,应该还需要更多的信息。我看不出有什么理由在这里同时设置
NotificationCoordinator
NotificationStrategy
NotificationCoordinator
实际上做了一件事,实施策略,为什么要添加另一个抽象?我与@Beyers分享这个问题。添加的抽象似乎没有必要。我也不太明白你在避免具体类通知背后的想法?Notification类只是一个独立的模型,其中包含数据,如要发送的消息。@RobinAnderPlas。。。然而,它“知道”通过什么方式发送。但我们现在可以转移到没完没了的架构讨论中。事实是:优化的目标是什么?这是这个问题的正确答案吗?它能正常工作吗?也许更适合CodeReview。。。拜耳,罗宾,如果你不知道为什么你应该分离这些顾虑,那么你必须阅读坚实的原则。在od通知和“抽象”的情况下,您可能是对的,但前提是它是一个POCO对象——您没有显示它的实现,所以很难说。在我的回答中,我还假设你知道什么是DI,并且你使用它。正如你们所说,你们的实现是有效的,它会一直有效,直到你们不得不改变一些事情,然后问题就会出现;)@Posio我不是反对SOLID。我的问题是,你为什么认为
通知协调员
违反了单一责任原则?它实际上只做一件事,那就是实施战略。
services.AddNotifiers();