C#: 在不相关的类之间共享属性、事件和方法

3

我需要向几个没有关联的类中添加以下内容:

private MyClass myclass;

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

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

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

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

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

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) { ... }
}

然后使用扩展方法来扩展所需的接口(即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) { ... }
}

第二种方式允许您创建一个新的包装层次结构,其中将包含没有共同基类的元素。

1

继承在时间上会变得棘手。我建议使用接口,这样您将拥有更多的灵活性。

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);

但是反射可能过于复杂。

谢谢。我考虑过这个,但理想情况下,我不仅想重构声明,还想重构实现。 - Mark13426
请查看编辑1。这是您想要的吗? - Orhan Tuncer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接