【问题标题】:C#: Share properties, events, and methods across unrelated classesC#:在不相关的类之间共享属性、事件和方法
【发布时间】:2016-02-18 07:10:29
【问题描述】:

我需要在几个不相关的类中添加以下内容:

private MyClass myclass;

private EventHandler clicked;
public event EventHandler Clicked { ... }

private bool enabled;
public bool Enabled { ... }

private void HandleClicked(object sender, EventArgs e) { ... }

问题是这些类是第三方的,不一定共享同一个直接基类,尽管它们最终都继承自一个名为 View 的类。现在,我最终为每个创建自己的子类并复制粘贴相同的代码,这会导致不必要的重复。

有什么方法可以有意义地重构它?

【问题讨论】:

  • 添加更多代码... ppl 将无法为您提供帮助
  • 我不确定为什么需要更多代码。这是一个设计问题,它应该有一个通用的解决方案 IMO。此外,除了基本的事件/属性处理之外,代码没有做任何特殊的事情。
  • 如果它是通用的,那么它不会是特定于您的。是的,它可以被重构......但它再次是你的代码,并且在没有上下文的情况下做出了很多假设......并且不知道你是否听说过假设是什么;-)。如果它是通用的……那么只需使用抽象类/继承/接口……显示代码……除了使用通用 oop 技术之外,没有给我足够的上下文来想出任何东西。

标签: c# oop events


【解决方案1】:

其中一种方法是使用组合。创建将存储所有新事件\属性\方法的类:

public class Properties
{
  private MyClass myclass;

  private EventHandler clicked;
  public event EventHandler Clicked { ... }

  private bool enabled;
  public bool Enabled { ... }

  private void HandleClicked(object sender, EventArgs e) { ... }
}

然后使用Extension methods扩展需要的接口(即classA)

public static class NewInterfaces
{
   public static Properties Props(this classA)
   {  /* lookup required properties, from some associative storage */ }
}

用法如下:

var inst = new classA();
inst.Prop.Enabled = !inst.Prop.Enabled;

第二种方式它仍然是组合,但您将使用包装器:

public class Wrapper
{
  private object _wrapped;

  public Wrapper(classA obj)
  {
    _wrapped = obj;
  }

  public Wrapper(classB obj)
  {
    _wrapped = obj;
  }

  public int WrappedProperty
  { 
    get
    {
      var instA = _wrapped as classA;
      if (instA != null)
        return instA.SomeProperty1;
      var instB = _wrapped as classB;
      if (instB != null)
        return instB.SomeProperty2;
    }
  }

  private MyClass myclass;

  private EventHandler clicked;
  public event EventHandler Clicked { ... }

  private bool enabled;
  public bool Enabled { ... }

  private void HandleClicked(object sender, EventArgs e) { ... }
}

第二种方法允许您创建新的包装层次结构,该层次结构将包含没有公共基类的元素。

【讨论】:

    【解决方案2】:

    随着时间的推移,继承变得有问题。我建议改用接口,您将拥有更大的灵活性。

    public interface INewInterfaces
    {
        event EventHandler Clicked;
        bool Enabled { get; }
        void HandleClicked(object sender, EventArgs e);
    }
    
    public class NewClassA : ClassA, INewInterfaces
    {
        //...
    }
    
    public class NewClassB : ClassB, INewInterfaces
    {
        //...
    }
    

    编辑 1:

    如果您说 ClassX 非常相似,并且您想在所有这些不相关的类中使用相同的 HandleClicked 实现,您可以使用其他两种方法。

    1- 仍然继承

    创建一个接口并在您要使用的类中添加所有常用功能。这会将 ClassX 放在同一个家族中。然后创建一个通用类。

    public interface IExistingInterfaces
    {
        void SomeMethod();
    }
    
    public class NewClassA : ClassA, IExistingInterfaces
    {
        //Do nothing
    }
    
    public class NewClassB : ClassB, IExistingInterfaces
    {
        //Do nothing
    }
    
    
    public class MyClassForGeneralUse : IExistingInterfaces
    {
        private IExistingInterfaces _baseObject;
        public MyClassForGeneralUse(IExistingInterfaces baseObject)
        {
            _baseObject = baseObject;
        }
    
        //Write proxy calls for IExistingInterfaces 
        public void SomeMethod()
        {
            _baseObject.SomeMethod();
        }
    
        //Add new methods here
        public void HandleClicked(object sender, EventArgs e)
        {
    
        }
        //...
        //...
    }
    

    不是:第一部分是桥接模式,第二部分是装饰器模式

    2- 反射

      var propertyInfo = someObject.GetType().GetProperty("property name");
        if (propertyInfo == null)
            throw new Exception(string.Format("Property does not exist:{0}", condition.Property));
    
        var propertyValue = propertyInfo.GetValue(someObject, null);
        long longValue = (long)propertyValue;
    
        //You can get methods in a smilar manner and execute with
        result = methodInfo.Invoke(methodInfo, parametersArray);
    

    但反思可能有点过头了。

    【讨论】:

    • 谢谢。我考虑过这一点,但理想情况下,我不仅要重构声明,还要重构实现。
    • 请参阅编辑 1。这是您的意思吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 2015-03-29
    • 2013-07-25
    相关资源
    最近更新 更多