基类中的反射是一个糟糕的设计理念吗?
一般来说,基类中的反射可以达到一些好的和有用的目的,但我在这里遇到了一个进退两难的情况......使用反射,或者在真正应该公开的时候暴露公共工厂类从语义上讲是私有的(即不只是任何人都应该能够使用它们)。 我想这里有一些代码:
public abstract class SingletonForm<TThis> : Form
where TThis : SingletonForm<TThis>
{
private static TThis m_singleton;
private static object m_lock = new object();
private static ISingletonFormFactory<TThis> m_factory;
protected SingletonForm() { }
public static TThis Singleton
{
get
{
lock (m_lock)
{
if (m_factory == null)
{
foreach (Type t in typeof(TThis).GetNestedTypes(BindingFlags.NonPublic))
{
foreach (Type i in t.GetInterfaces())
{
if (i == typeof(ISingletonFormFactory<TThis>))
m_factory = (ISingletonFormFactory<TThis>)Activator.CreateInstance(t);
}
}
if (m_factory == null)
throw new InvalidOperationException(string.Format(
CultureInfo.InvariantCulture,
"{0} does not implement a nested ISingletonFormFactory<{0}>.",
typeof(TThis).ToString()));
}
if (m_singleton == null || m_singleton.IsDisposed)
{
m_singleton = m_factory.GetNew();
}
return m_singleton;
}
}
}
}
现在,这段代码对我有用,但它是一个可怕的拼凑和/或一个非常糟糕的主意吗? 另一个选项是将 Factory 的类型作为类型参数传递,但由于可见性限制,Factory 类必须是公共的,这意味着任何人都可以调用它来创建不应该的实例。
In general reflection in a base class can be put to some good and useful ends, but I have a case here where I'm between a rock and a hard place... Use Reflection, or expose public Factory classes when they really should be private semantically speaking (ie. not just anyone should be able to use them). I suppose some code is in order here:
public abstract class SingletonForm<TThis> : Form
where TThis : SingletonForm<TThis>
{
private static TThis m_singleton;
private static object m_lock = new object();
private static ISingletonFormFactory<TThis> m_factory;
protected SingletonForm() { }
public static TThis Singleton
{
get
{
lock (m_lock)
{
if (m_factory == null)
{
foreach (Type t in typeof(TThis).GetNestedTypes(BindingFlags.NonPublic))
{
foreach (Type i in t.GetInterfaces())
{
if (i == typeof(ISingletonFormFactory<TThis>))
m_factory = (ISingletonFormFactory<TThis>)Activator.CreateInstance(t);
}
}
if (m_factory == null)
throw new InvalidOperationException(string.Format(
CultureInfo.InvariantCulture,
"{0} does not implement a nested ISingletonFormFactory<{0}>.",
typeof(TThis).ToString()));
}
if (m_singleton == null || m_singleton.IsDisposed)
{
m_singleton = m_factory.GetNew();
}
return m_singleton;
}
}
}
}
Now, this code works for me, but is it a horrible kludge and/or a really bad idea? The other option is passing in the Factory's type as a type paramater, but then due to visiblity limitations, the Factory class must be public which means anyone can call it to make instances when they shouldn't be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在处理泛型时,您经常必须使用反射。 从这方面来说我认为你很好。
也就是说,我在这里看到两种形式的代码气味。 然而,它们可能是由于代码卫生造成的,所以我只会对它们进行评论:
首先,您的静态属性是通用项目。 我 99.999% 确信这甚至无法编译。 如果确实如此,那就是不好的形式。
其次,您似乎为每次调用
Bar
返回一个新实例。 对于吸气剂来说,这也被认为是不好的形式。 我会使用一个名为 CreateBar() 或类似方法的方法。When dealing with generics, you frequently have to use reflection. In that regard I think you're fine.
That said, I see two forms of code smell here. They may be due to code sanitation, however, so I'll just comment on them:
First, your static property is of a generic item. I'm 99.999% sure this will not even compile. If it does, it's bad form.
Second, you appear are returning a new instance for every call to
Bar
. This is also considered bad form for a getter. I would instead have a method called CreateBar() or something similar.使用自定义属性也可以更好地处理这种情况,您可以在其中显式定义要使用的类型。
你的单身财产现在变成
This situation is also better handled with custom attributes where you can explicitly define the type to use.
Your singleton property now becomes
如果可能的话,如果可以的话,我会尽量避免使用反射。
为此,您可以尝试使用抽象工厂模式来解决直接公开的问题公共工厂类型,具体取决于您的情况。
维基百科示例(在 Java 中)的说法是,您创建一个工厂接口,您的工厂类实现该接口,然后您的代码中的某些内容会生成您需要的工厂并将其作为工厂接口返回。
另一种方法是为抽象工厂创建一个抽象类而不是接口,然后在该抽象类中创建一个静态方法以返回所需的类型工厂。
If it's possible, I'd try to avoid using reflection if you can get away with it.
To do this, you could try using an Abstract Factory pattern to get around the problem of directly exposing a public factory type, depending on your situation.
The way the Wikipedia example puts it (in Java) is that you create a factory interface, which your factory class implements, then you have something in your code generate the factory you need and return it as the factory interface.
Another way of doing this would be to create an abstract class instead of an interface for your abstract factory, then create a static method within this abstract class for returning the type factory you need.
仅供参考,以下内容可以减少
为
Just an FYI, the following can be reduced from
to