好的,编辑了澄清代码:
问题:如何从[MyAttr("...")]
中访问TestClassOne/Two
中的BaseClass.TheAttribute
属性?
除TestClassOne / Two之外的所有类都将编译到我的“核心”中,并作为开发平台提供给客户。 TestClassOne / Two是由客户开发的,因此在“核心”中无法了解TestClassOne / Two。
下面的代码被编译成“核心”并以dll的形式交付给客户。
[TestMethod()]
public void AttrTest()
{
var one = new TestClassOne();
var attrOne = one.MyTestProperty.TheAttribute;
var two = new TestClassTwo();
var attrTwo = two.MyTestProperty.TheAttribute;
}
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
}
public class BaseClass
{
public string TheAttribute
{
get {
// Here I would like to get the "[MyAttr("...")]" from the classes in the bottom
return null;
}
}
}
public class SubClass : BaseClass
{
}
以下代码由客户(使用我的dll)开发
public class TestClassOne
{
[MyAttr("Attribute one")]
public SubClass MyTestProperty = new SubClass();
}
public class TestClassTwo
{
[MyAttr("Attribute two")]
public SubClass MyTestProperty = new SubClass();
}
答案 0 :(得分:2)
编辑3:
您可以遍历调用堆栈,在相关类中的相关成员中查找相关属性。试试这个:
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
public string getAttr()
{
return _test;
}
}
public class BaseClass
{
private string theString;
public BaseClass()
{
StackTrace callStack = new StackTrace();
for ( int i = 0; i < callStack.FrameCount; i++ )
{
Type t = callStack.GetFrame(i).GetMethod().DeclaringType;
foreach ( MemberInfo m in t.GetMembers().Where(x => typeof(BaseClass).IsAssignableFrom(x.Type)) )
{
foreach ( var z in m.GetCustomAttributes(typeof(MyAttr)) )
{
MyAttr theAttr = z as MyAttr;
if ( z!= null )
{
theString = z.getAttr();
return;
}
}
}
}
}
public string Test
{
get {
return theString;
}
}
}
这要求您的客户始终在声明它的类中初始化SubClass成员。如果他们开始派生TestClassOne
或者拥有它并且TestClassTwo
派生自初始化成员的公共类,则此代码将会中断。
通过巧妙地使用反射,您可以扩展上面的代码以涵盖更多用例,但这超出了这个问题的范围。
编辑2:
没有。对不起,但你想做的事情是不可能的。 SubClass
的实例没有“正常”的方式来知道它是在某个其他对象的成员字段中声明,还是在数组中的元素中或在堆栈中的临时变量中声明,或者其他什么。因此,该实例无法访问声明它的成员字段的属性。
(我想你可能想尝试访问垃圾收集器来找出this
对象所在的内存位置,但这可能超出了这个问题的范围,无论如何,不是我的东西知道怎么做。)
我怀疑你的问题完全在别处。也许您需要要求您的客户从一个共同的抽象类派生TestClassOne
和TestClassTwo
。也许他们需要从BaseClass
自己派生出来。也许你需要在构造函数中添加参数。也许你需要提供一个完全不同的界面。除非您提供有关您的特定业务要求的更多信息,否则我们无法知道。
修改强>
要访问在MyTest成员上声明的属性,请尝试以下几行:
public class BaseClass
{
public string Test
{
get {
var attr = typeof(Test).GetMembers().Where(x => x.Type == this.GetType()).First().GetCustomAttributes(true);
return null;
}
}
}
这将在类Test
中搜索与this
类型相同的成员,并在该成员上查找属性。
(我这里没有我的Visual Studio,检查确切的Where
语法,但它应该非常接近......)
原始答案:
您的属性在类MyTest
的{{1}}成员上声明。但是,您正在课堂Test
上进行GetCustomAttributes
。
试试这个:
SubClass
应该得到你想要的东西。
答案 1 :(得分:2)
您可以直接从Test
类型获取:
var result = typeof (Test)
.GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
.GetCustomAttribute<MyAttr>();