C# 从foowriter类型的一组类中检索公共属性

C# 从foowriter类型的一组类中检索公共属性,c#,reflection,C#,Reflection,我有一组类,它们都扩展了相同的基类,比如 fooboo:foowriter,foobar:foowriter。这些都是具有不同扩展名的输出文件,例如fooboo-->.boo和foobar-->.bar文件 我正在使用反射来获取扩展foowriter的所有具体类型的列表,我需要获取这些类可以生成的所有扩展的列表,即{.boo“,.bar”} 目前,每个foowriter都知道它可以生成什么格式,这是一个只读字段。我渴望将这些知识封装在每个具体的类中,而不是在某个额外的类中实现GetOutputE

我有一组类,它们都扩展了相同的基类,比如
fooboo:foowriter,foobar:foowriter
。这些都是具有不同扩展名的输出文件,例如
fooboo-->.boo
foobar-->.bar
文件

我正在使用反射来获取扩展
foowriter
的所有具体类型的列表,我需要获取这些类可以生成的所有扩展的列表,即
{.boo“,.bar”}

目前,每个
foowriter
都知道它可以生成什么格式,这是一个只读字段。我渴望将这些知识封装在每个具体的类中,而不是在某个额外的类中实现
GetOutputExtension():其中T:foowriter
方法,因为这会将所有
foowriter
与该额外的实用程序类耦合

我真的不想实例化具体的类,因为这可能是一个繁重的操作


从一组类型中获取公共属性而不实例化它们的好模式或方法是什么?

您可以在基本公共类上创建静态属性
foowriter

然后可以在每个子类中重写此属性并返回所需的数据。属性是静态的,因此不需要实例化

public class foowriter
{
    public static string Extension
    {
        get { throw new NotImplementedException(); }
    }

}

public class foobar
{
    public static string Extension
    {
        get { return "bar"; }
    }

}

public class fooboo
{
    public static string Extension
    {
        get { return "boo"; }
    }

}

使用反射查找静态属性

使用反射获取所有具体类:

var type = typeof(foowriter);
var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(t => type.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface);
然后使用反射获取您姓名的所有字段值:

var outputFormats = new List<string>();
foreach (var t in types)
{
var prop = t.GetFields().First(i => i.Name == "outputFormat");
    outputFormats.Add(prop.GetValue(null));
}
var outputFormats=new List();
foreach(类型中的var t)
{
var prop=t.GetFields().First(i=>i.Name==“outputFormat”);
Add(prop.GetValue(null));
}

这样做的缺点是它不允许编译时检查。派生类也没有outputFormat字段的强制执行:-/

一个选项是创建自定义属性。这样,您就可以将扩展与类关联起来,而不必实例化它们

用法:

[Output(Extension = ".boo")]
public class fooboo : foowriter { ... }

[Output(Extension = ".bar")]
public class foobar : foowriter { ... }
缺点是这不会在编译时强制执行


编辑:但是,您可以为它编写单元测试。

不能使用静态虚拟测试。(例如,
抽象类a{public static virtual string tau;}
类b:a{public static override string tau=“bbb”;}
未编译)对不起,对了。静态成员不需要虚拟。NotImplementedException非常棒!是的,你不会。但这样你就不会有反省了。不能将静态成员标记为抽象,也不能使用静态方法实现接口。岩石和坚硬的地方。从本质上说,我想要的正是这个,但我不能,所以我需要一个更好的选择,在不影响编译时检查的情况下。我非常确定要确保它的安全(即避免潜在的运行时错误),我必须有一个可以检查的实例(比如FooWriterBuilder的集合)。由于实施/使用它们所需的结构变化,因此不太热衷于这样做:/Good call。。。您还可以将单元测试响应应用于所有其他解决方案。。查找实现反射接口的所有类,并检查它们是否具有预期的静态属性/field/const/attribute。好球!(我喜欢单元测试!)