C# - 通过相同的方法传递不同类型的对象

2024-01-10

原始问题

所以我有这 3 个对象......

public class obj1
{
  public int Id { get; set; }
  public string Name { get; set; }
}

public class obj2
{
  public int AccNum { get; set; }
  public string Name { get; set; }
}

public class obj3
{
  public string Email { get; set; }
  public string Phone { get; set; }
}

...以及一种应该接收其中之一的方法,在评估对象类型之后,程序应该决定调用哪个函数。

我尝试过使用泛型,但它没有按我的预期工作。到目前为止,这就是我所拥有的......

    public class NotificationHelper: INotificationHelper
    {

        public bool SendNotification<TNotInfo>(TNotInfo obj) where TNotInfo : class
        {
            if (contract.GetType() == typeof (obj1))
            {
                var sender = new SendSMS();
                return sender.Send(obj);
            }
            if (contract.GetType() == typeof(obj2))
            {
                var sender = new SendPush();
                return sender.Send(obj);
            }
            else
            {
                var sender = new SendEmail();
                return sender.Send(obj);
            }
        }
    }

但我收到错误“无法从 TNotInfo 转换为 Models.obj1”。有什么办法可以克服这个问题吗?或者我必须改变我的逻辑?

感谢任何帮助,提前致谢。

*Edit

using System;

namespace EmailNotifications
{

    public interface IEmailNotification
    {
        void SendEmailNotification();
    }

    public class EmailNotificationA : IEmailNotification
    {

        public void SendEmailNotification(Contract1 a)
        {
            Console.WriteLine($"Sending EmailNotificationA ({a})");
        }
    }

    public class EmailNotificationB : IEmailNotification
    {
        public void SendEmailNotification(Contract2 b)
        {
            Console.WriteLine($"Sending EmailNotificationB ({b})");
        }
    }

    public class EmailNotificationC : IEmailNotification
    {

        public void SendEmailNotification(Contrac3 c)
        {
            Console.WriteLine($"Sending EmailNotificationC ({c})");
        }
    }

    public class EmailNotificationService
    {
        private readonly IEmailNotification _emailNotification;

        public EmailNotificationService(IEmailNotification emailNotification)
        {
            this._emailNotification = emailNotification;
        }

        public void ServiceHelper()
        {
            _emailNotification.SendEmailNotification();
        }
    }
}

上述解决方案是我应用策略设计模式试图实现的目标。但我无法设法让我的接口方法接收不同的对象,这是必需的,因为每个通知都有自己的实现。正如上面的无工作示例所示,我对同一方法有 3 种不同的实现,它们都接收不同的对象。知道如何使这个逻辑发挥作用吗?


这就是界面设计的目的。首先定义一个通用接口:

public interface INotifier
{
    bool Notify();
}

其次,将其实施到您的objX课程:

public class obj1 : INotifier
{
    public int Id { get; set; }
    public string Name { get; set; }

    public bool Notify()
    {
        var sender = new SendSMS();
        return sender.Send(this);
    }
}

public class obj2 : INotifier
{
    public int AccNum { get; set; }
    public string Name { get; set; }

    public bool Notify()
    {
        var sender = new SendPush();
        return sender.Send(this);
    }
}

public class obj3 : INotifier
{
    public string Email { get; set; }
    public string Phone { get; set; }

    public bool Notify()
    {
        var sender = new SendEmail();
        return sender.Send(this);
    }
}

最后,更改通知方法以接受接口类型作为参数:

public class NotificationHelper : INotificationHelper
{
    public bool SendNotification(INotifier obj)
    {
        return obj.Notify();
    }
}

编辑(2019):

我正在重新审视这个答案,因为它似乎得到了相当多的关注。 OP 可能早已继续前进,但对于其他可能偶然发现这个答案的人来说,这是另一个解决方案。

我仍然相信接口是正确的出路。然而,上面建议的接口非常通用,最终并不是很有用。它还遇到了一些 DRY 违规,因为正如 Fabio 在评论中所说,如果两个objX类以相同的方式实现通知,这种方法迫使您在它们之间复制代码。

不是一个全局接口,而是为每个特定通知任务提供接口,即ISMSNotification, IPushNotification, IEmailNotification。然后,您可以使用 mixin 模式为每个接口实例提供 send 方法的默认实现:

interface ISmsNotifier
{
  int SmsId { get; }
  string SmsName { get; }
}

static class ISmsNotifierExtensions 
{
  public static bool NotifySms(this ISmsNotifier obj) 
  {
    var sender = new SendSMS();
    return sender.Send(obj);
  }
}

// ---------------------------------------------

interface IPushNotifier 
{
  int PushAccNum { get; }
  string PushName { get; }
}

static class IPushNotifierExtensions 
{
  public static bool NotifyPush(this IPushNotifier obj) 
  {
    var sender = new SendEmail();
    return sender.Send(obj);
  }
}

// ---------------------------------------------

interface IEmailNotifier 
{
  string EmailAddress { get; }
  string EmailPhone { get; }
}

static class IEmailNotifierExtensions 
{
  public static bool NotifyEmail(this IEmailNotifier obj) 
  {
    var sender = new SendEmail();
    return sender.Send(obj);
  }
}

然后您可以在objX像这样的类:

public class obj1 : INotifier, ISmsNotifier 
{
  public int SmsId { get; set; }
  public string SmsName { get; set; }

  public bool Notify() => this.NotifySms();
}

public class obj2 : INotifier, IPushNotifier
{
    public int PushAccNum { get; set; }
    public string PushName { get; set; }

    public bool Notify() => this.NotifyPush();
} 

public class obj3 : INotifier, IEmailNotifier
{
    public string EmailAddress { get; set; }
    public string EmailPhone { get; set; }

    public bool Notify() => this.NotifyEmail();
}

请注意,使用这种方法不仅可以轻松支持使用相同通知系统的对象,还可以支持具有以下功能的对象:multiple通知系统:

public class obj4 : INotifier, IEmailNotifier, IPushNotifier
{
    public int PushAccNum { get; set; }
    public string PushName { get; set; }
    public string EmailAddress { get; set; }
    public string EmailPhone { get; set; }

    public bool Notify() => this.NotifyEmail() && this.NotifyPush();
}

您可能会注意到这种方法使得NotificationHelper已过时,因为不再需要通过处理步骤传递对象来确定通过哪个通知系统处理对象。这是真的,也许也是正确的,因为对象应该完全能够自己决定这一点(取决于你处理这个问题的心态)。然而,NotificationHelper可能仍然有其用途,例如,如果您想要预处理发送到通知服务的信息,或者如果您想要一个公共入口点来帮助模拟和测试。

C#8 注意:

C# 8 的一项拟议功能是能够为接口提供接口定义本身内方法的默认实现。当(如果)发生这种情况时,您不需要再使用 mixin 模式,并且可以直接在接口中定义默认方法实现。该功能尚未最终确定,但它可能看起来像这样:

interface ISmsNotifier 
{
  int SmsId { get; }
  string SmsName { get; }

  public bool NotifySms() 
  {
    var sender = new SendSMS();
    return sender.Send(this);
  }
}

// ---------------------------------------------

interface IPushNotifier 
{
  int PushAccNum { get; }
  string PushName { get; }

  public bool NotifyPush() 
  {
    var sender = new SendEmail();
    return sender.Send(this);
  }
}

// ---------------------------------------------

interface IEmailNotifier 
{
  string EmailAddress { get; }
  string EmailPhone { get; }

  public bool NotifyEmail() 
  {
    var sender = new SendEmail();
    return sender.Send(this);
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# - 通过相同的方法传递不同类型的对象 的相关文章

随机推荐