c# - 动态类是这种情况还是……?

标签 c# class dynamic properties factory

关于这个问题我甚至不知道该搜索什么,所以我想把它贴在这里。
假设我有很多接口,比如…

/// <summary>
/// All interesting classes will implement this interface
/// </summary>
interface IMasterInterface {}

/// <summary>
/// Interface to represent someone that creates / produces goods
/// </summary>
interface IProduceGoods : IMasterInterface { int Prop1 {get;} }

/// <summary>
/// Interface to represent someone that buys / consumes goods
/// </summary>
interface IConsumeGoods : IMasterInterface { int Prop2 {get;} }

/// <summary>
/// Interface to represent someone that stores goods
/// </summary>
interface IStoreGoods : IMasterInterface { double Prop3 {get;} string name {get;}}

/// <summary>
/// Interface to represent someone that enjoys looking at goods
/// </summary>
interface IEnjoyLookingAtGoods : IMasterInterface { int Prop4 {get;} DateTime Prop5 {get;} }

现在,我有一些我知道我今天想要的组合,比如:
/// <summary>
/// Class to represent a farm which grows and stores crops
/// </summary>
class Farm : IProduceGoods, IStoreGoods {/*...*/}

/// <summary>
/// Class to represent a merchant who buys goods and stores them
/// </summary>
class Merchant : IConsumeGoods, IStoreGoods {/*...*/}

/// <summary>
/// Window Shopper represents someone who doesn't buy anything and only looks
/// </summary>
class WindowShopper : IEnjoyLookingAtGoods{ /*...*/ }

现在我很高兴我有了几节课,但是明天,我想,如果有人真的从商家那里买了一节课,我会去我的代码并添加
/// <summary>
/// Princesses have lots of money to buy stuff and lots of time to look at stuff
/// </summary>
class Princess : IEnjoyLookingAtGoods, IConsumeGoods {/*...*/}

现在,我觉得我不应该这么做…
我想做的是有一个工厂(或类似的工厂)并说:
IMasterInterface princess = MyFactory.Create(IEnjoyLookingAtGoods, IEnjoyLookingAtGoodsParameters, IConsumeGoods, IConsumeGoodsParameters)

/// This should be true
((princess is IEnjoyLookingAtGoods) && (princess is IConsumeGoods))

本质上,我想告诉工厂使用哪些接口来构造对象。我有一个容器,上面有一个imasterinterface列表
/// <summary>
/// My container class for interesting objects
/// </summary>
class InterestingObjectContainer
{ public ReadOnlyCollection<IMasterInterface> InterestingObjects {get;} }

现在,问题的关键就在这里。让所有感兴趣的类实现imasterinterface的原因是能够有一个列表并使用更具体的接口作为过滤器。或许以下几点会更清楚:
/// <summary>
/// I want to see the net population of producers and get there total production
/// </summary>
class ProducerProductionCalculator
{
  // THIS IS WHERE THE MEAT OF THE QUESTION RESIDES!
  ProductionResults Calculate(InterestingObjectContainer interestingObject)
  {
    List<IProduceGoods> producers = interestingObject.InterestingObjects.OfType<IProduceGoods>(); // Perhaps more interest LINQ
    return DoSomethingWithListToAggregate(producers);
  }
}

通过过滤到更具体的接口,我现在可以指望传递给
DosomethingWithListToAggregate(ICollection生产者)
具有iproducegoods类的方法/属性。
我考虑过用字典和字符串属性查找来实现这一点,但感觉我可以用这种方式编写更强类型的代码,并确保某个地方的简单拼写错误不会把一切都弄糟。
总之,我想总结如下:
这是一种在对象上实现变量属性的糟糕方法吗?如果是的话,还有更好的方法。如果没有,是否有办法在工厂中创建对象,正如我在上面解释的那样?
编辑:
我觉得做这个主意不错,很酷。我想知道如何创建一个工厂,它接受一个接口的参数,这个接口只有属性,而且属性只有getter(我认为这是一个重要的点)和属性的属性值,并返回一个实现接口并定义了所有属性的对象。
例如,
/// <summary>
/// Factory to create any combination of properties
/// </summary>
class FactoryForInterestingObjects
{
  public static IMasterInterface Create(
  List<KeyValuePair</*what goes here is the interface that I want to use,
                      what goes here are the parameter values that 
                      should be returned by the getter */>> );
}

我将把所有接口及其参数值传递给工厂,它将创建一些实现这些接口并具有这些值的类。希望这更清楚一点?
编辑2:如何使用decorator?
根据我对decorator的了解,您可以扩展对象的功能。太酷了。但是,您必须提前知道如何扩展该功能。你不能随便这么做。
考虑到我的代码基础如上所述,我想使用decorator。
我会说:
// Edited to be correct
class EnjoyLookingDecorator : IEnjoyLookingAtGoods
{
  private IMasterInterface instance;
  public EnjoyLookingDecorator(IMasterInterface wrappedObject)
  { this.instance = wrapped Object;}

  #region Implementation of IEnjoyLookingAtGoods
  /*...*/
  #endregion
}

编辑4:
我还是觉得这样不行。在您的示例中,我失去了包含的类接口,我必须将其重定向下来。例如,
class EnjoyLookingDecorator : IEnjoyLookingAtGoods
{
  private IMasterInterface instance;
  public EnjoyLookingDecorator(IMasterInterface concrete)
  { this.instance = concrete;}

  #region Implementation of IEnjoyLookingAtGoods here
  /*...*/
  #endregion

  bool Is<T>() //this should be in the IMasterInterface
  {
     return this is T or instance is T;
  }
}

class ConsumesGoodsDecorator : IConsumeGoods
{
  private IMasterInterface instance;
  public ConsumesGoodsDecorator (IMasterInterface concrete)
  { this.instance = concrete;}

  #region Implementation of IConsumeGoods here
  /*...*/
  #endregion

  bool Is<T>()
  {
     return this is T or instance is T;
  }
}

所以当你
IMasterInterface princess = new MasterClass() //whatever your concrete type is named
princess = new ConsumesGoodsDecorator(new EnjoyLookingDecorator(princess))

你再也做不到公主。财产你的外表看起来像装饰你失去了所有的财产。这不是我想要的。保留属性的唯一方法是重定向
class ConsumesGoodsDecorator : IConsumeGoods, IEnjoyLookingAtGoods
{
  private IMasterInterface instance;
  public ConsumesGoodsDecorator (IMasterInterface concrete)
  { this.instance = concrete;}

  #region Implementation of IConsumeGoods here
  /*...*/
  #endregion

  #region Redirect all the IEnjoyLookingAtGoods Property Getters to instance
  /* ... */
  #endregion

  bool Is<T>()
  {
     return this is T or instance is T;
  }
}

通过执行重定向,我们必须实现接口。然后所有的组合都必须有代码,这是我试图避免的。我不需要限制接口的组合。
编辑5:
也许我的问题还不清楚。想象一下上面的接口,它们的属性被填充。
如果工厂能这样做:
/// <summary>
/// Factory to create any combination of properties
/// </summary>
class FactoryForInterestingObjects
{
  public static IMasterInterface Create(
    List<KeyValuePair<Type t, ArgSet customArguments>> interfaces))
  {
    object baseObject;
    foreach(KeyValuePair<Type, ArgSet> interface in interfaces)
    {
       AddInterface(interface, object);
    }
  }

  private static void AddInterface(KeyValuePair<Type, ArgSet> interface, ArgSet arguments)
  {
     // Delegate this to someone else
     if(interface.Key is typeof(IProduceGoods))
     {
       IProduceGoodsExtensions.AddInterface(o, interface.value);
     }
  }
}

public static class IProduceGoodsExtensions
{
   public static void AddInterface(object o, ArgSet arguments)
   {
      // do something to object to make it implement IProductGoods
      // and make all the getters return the arguments passed in ArgSet
   }
}

我意识到这并不是它真正的工作方式,但它说明了我试图表达的观点。我希望对象实现接口的动态组合,并具有setter的默认值。
即使我可以让工厂写一个包含代码的文本文件:
/// <summary>
/// Auto Generated by Factory to create a new type on the fly
/// </summary>
class ClassImplementingIProduceGoodsAndIEnjoyLookingAtGoods : IProduceGoods, IEnjoyLookingAtGoods
{
  // From IProduceGoods
  public int Prop1 {get; private set;}
  // From IEnjoyLookingAtGoods
  public int Prop4 {get; private set;}
  public DateTime Prop5 {get; private set;}
  public ClassImplementingIProduceGoodsAndIEnjoyLookingAtGoods(int prop1, int Prop4 , DateTime Prop5)
  {
    this.Prop1 = prop1; this.Prop4 = Prop4; this.Prop5 = Prop5;
  }
}

然后编译这个类并以某种方式允许我创建它的实例。这就是我要找的。希望这更有意义。
编辑6:
这是我可能会采用的解决方案,因为我在这一点上看不到替代方案。
//Update Master Interface
interface IMasterInterface
{
   bool Is(Type t);
   IMasterInterface As(Type t);
}

/// <summary>
/// Class to build up a final object
/// </summary>
class CompositionObject : IMasterInterface
{
  ICollection<IMasterInterface> parts;
  CompositionObject(IMasterInterface object){ parts = new List<IMasterInterface(object);}
  bool Is(Type t)
  {
     foreach(IMasterInterface part in parts)
     { if (part is t) return true; // not sure on this off top of head
     }
      return false;
  }

  IMasterInterface As(Type t)
  {
    foreach(IMasterInterface part in parts)
    { if(part is t) return part; }
  }

  bool Add(IMasterInterface interface)
  { this.Is(typeof(interface)) return false; // don't add again
    this.parts.Add(interface) }
}

现在我的工厂可以只返回这些组合对象,只要被调用,我就可以安全地向下转换。我觉得可能有一种方法可以使用泛型来避免强制转换。
任何实现imasterinterface的具体类都可以在调用as时简单地返回自身。
编辑3:
谢谢大家的评论。我很高兴我公布了我对这个图案的无知;谢谢你的澄清!我爱这个网站和所有可爱的人在那里!啊!

最佳答案

试着看看装饰设计模式。就我所见,它是针对您所想到的那种情况,即对象可以包含从一组属性中提取的一组混合属性。在decorator模型中,每个属性都是一个自己的类,您可以有效地动态连接这些类以创建具有所需属性的对象。
要实现过滤,您需要使用某种迭代器遍历装饰器链,以查看您要测试的对象是否包含您要查找的迭代器。
我还没有使用C语言中的装饰器,只是C++,但是我发现它是一种非常有用和灵活的方法。如果你发现自己创建了更多更专业的类来表示“property”类的交集,那么我认为decorator很有帮助。
有关此模式的信息,请参见Decorator Design Pattern in C#。(购买并阅读gof设计模式书!)

关于c# - 动态类是这种情况还是……?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7583632/

相关文章:

c# - JSON.NET:反序列化包含从接口(interface)派生的对象列表的类

c# - Linq 中的 DataLayer 具有不同版本的数据模型

c - 如何让用户确定全局变量的数组大小?

c# - 在对子类使用 'dynamic' (C#) 时,.NET 4 如何决定调用哪个方法?

java - 如何在返回接口(interface)引用时知道将使用哪个实现

html - YouTube 嵌入动态大小与最小和最大大小

c# - RSA C# 加密 Java 解密

c# - WCF SOAP 服务为 HTTPS 终结点返回 404 Not Found

iphone - 如何实现全局静态类

python - 通过子类化 `type` 类来实现类描述符