3

这可能是一个愚蠢的问题,但我正在开发一个组件,并且我有一个具有如下属性的类

public class Grid()
{
 ..
 public IDecorator Decorator { get; set;}

}

我想要的是让用户指定他们自己的自定义类,以下列方式实现 IDecorator

...BuildGrid(
grid=>{
..
grid.Decorator =  [CustomNameSpace].[DecoratorClass] 
//as in 
grid.Decorator =  Com.MyCompany.DivDecorator
..
});

Com.MyCompany.DivDecorator 实现 IDecorator 接口。那么我应该如何在没有最终用户指定“new”关键字的情况下做到这一点,如

grid.Decorator = new Com.MyCompany.DivDecorator();

我知道我在这里遗漏了一些关键的 c# 概念。

谢谢

[编辑]

我试图做一些类似于位于此处的 Java DisplayTag 库

http://www.displaytag.org/1.2/tut_decorators.html

他们这样做的方式是

...decorator="org.displaytag.sample.Wrapper"

所以我想而不是

public IDecorator Decorator { get; set;}

我应该做

public String Decorator (get; set;}

然后在内部使用 TypeOf() 来解决它....只是想知道是否有任何其他方法可以在 C# 中优雅地做到这一点。

谢谢

4

5 回答 5

8

那么你可以使用工厂方法:

public class DivDecorator
{
    public static IDecorator Create()
    {
        return new Com.MyCompany.DivDecorator()
    }
}

...

grid.Decorator = Com.MyCompany.DivDecorator.Create();

或单例:

public class DivDecorator
{
    public static readonly IDecorator Instance = new DivDecorator();
}

...

grid.Decorator = Com.MyCompany.DivDecorator.Instance;

在这两种情况下,您只是将new操作员移动到不同的位置。

或者,您可以让用户指定类型,然后您必须担心在需要时实例化它:

public class Grid
{
    public Type DecoratorType { get; set; }

    private IDecorator CreateDecorator()
    {
        return (IDecorator)Activator.CreateInstance(this.DecoratorType);
    }
}

...

grid.Decorator = typeof(Com.MyCompany.DivDecorator);

或者更好的是,使用泛型:

public class Grid<T> where T : IDecorator, new
{
    private T CreateDecorator()
    {
        return new T();
    }
}

BuildGrid<Com.MyCompany.DivDecorator>(grid => ... );
于 2013-07-30T15:17:11.827 回答
5

如果我了解您要查找的内容,则可以使用泛型:

public class Grid<TDecorator> where TDecorator : IDecorator, new() {

    private readonly TDecorator _decorator;

    public Grid() {
        _decorator = new TDecorator();
    }

    public TDecorator Decorator { get { return _decorator; } }
}

他们会通过调用得到一个网格:

var myGrid = new Grid<MyDecorator>();
于 2013-07-30T15:19:27.733 回答
3

您可以使 BuildGrid 通用,并指定一个 new() 约束。

例如BuildGrid<T>() where T : IDecorator, new()

虽然我不是 100% 清楚你想要做什么。

于 2013-07-30T15:19:11.843 回答
1

鉴于您有一个接口,您将在某处创建一个实例。您可以注入它(请参阅 IOC 模式或实例工厂模式)

有各种场景。但了解工厂模式会有所帮助

1)类在程序集中。发现类型 获取实现接口的所有类型 并创建实例 http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

2)代码是外部的, http: //msdn.microsoft.com/en-us/library/dd460648.aspx

3)或文件 http://msdn.microsoft.com/en-us/library/system.reflection.assembly.load%28v=vs.110%29.aspx

于 2013-07-30T15:33:51.707 回答
0

感谢所有帮助过我的人!我决定使用 pswg 的 Activator.CreateInstance 方法。原因是,对于网格组件,我有一个表级装饰器,然后网格的每一列也可以有自己的装饰器。如在

@Model.[MyIEnumberable].BuildGrid<Product>(grid=>{
grid.ShowHeader = false;
grid.CellSpacing = 0;
grid.CellPadding = 0;
grid.Decorator = "Com.MyCompany.DivDecorator";
grid.columns(
        grid.column(HeaderText: "First Column", Decorator:"Com.MyCompany.FirstColumnDecorator"...),
        grid.column(HeaderText: "Second Column", Decorator:"Com.MyCompany.SecondColumnDecorator"..),
        grid.column(HeaderText: "ThirdColumn", Text:@item.ProductID),
        grid.column(HeaderText: "ThirdColumn", Text:@item.[A Property only exist in grid.Decorator, achieved using dynamic/DynamicObject])
)
})

所以考虑到我的情况,因为每列都可能有自己的装饰器类。所以我将不得不为它们使用 Activator.CreateInstance。

再次感谢大家的帮助!!再次感谢您的宝贵时间!!

[编辑]。在阅读了 pswg 的最后两条评论后,泛型方法是要走的路!

于 2013-07-30T16:47:38.513 回答