什么是类型?

时间:2013-01-28 23:41:06

标签: c# types

我在代码中定义Type时遇到问题。让我们从Abc开始。

public partial class Abc {
    public static String AbcName="wtf";

    public String Name {
        get;
        set;
    }
}

好的, Abc已完成 。这是后来的测试课程。我有要求返回MyClass实例的对象或类型,这里是

    public partial class MyClass {
        public const BindingFlags
            Universal=BindingFlags.NonPublic|BindingFlags.Public,
            WithObject=Universal|BindingFlags.Instance,
            WithClass=WithObject|BindingFlags.Static,
            ForGive=Universal|BindingFlags.SetProperty|BindingFlags.SetField,
            ForGet=Universal|BindingFlags.GetProperty|BindingFlags.GetField,
            ForDo=BindingFlags.InvokeMethod|WithObject|WithClass;

        public MyClass GetTypeImpl() {
            if(null!=target)
#if TARGET_AS_TYPE
                return new MyClass(target as Type??target.GetType());
#else
                return new MyClass(target.GetType());
#endif
            else
                return new MyClass(typeof(object));
        }

        public object GetValue(String name) {
            var invokeAttr=ForGet|WithClass;
            var type=(Type)this.GetTypeImpl().target;
            return type.InvokeMember(name, invokeAttr, default(Binder), target, default(object[]));
        }

        public MyClass(object x) {
            this.target=x;
        }

        public object target;
    }

请注意,该代码用于表示我的班级。实际代码中的GetValue在内部调用,消费代码永远不会获得MyClass类型以外的对象。也就是说,实际代码中的 MyClass中的每个方法实际上都会返回MyClass 的实例。 在这里,我们看到带有TARGET_AS_TYPE的条件编译,这就是这个问题的重点。

考虑以下测试代码

    public partial class TestClass {
        public static void TestMethod() {
            var abc=
                new Abc {
                    Name="xyz"
                };

            var x=new MyClass(abc);
            var abcName=x.GetValue("Name");
            var y=new MyClass(x.GetTypeImpl().target);

#if TARGET_AS_TYPE
            var wtf=y.GetValue("AbcName");
            var fullName=y.GetValue("FullName"); // exception thrown
#else
            var fullName=y.GetValue("FullName"); 
            var wtf=y.GetValue("AbcName"); // exception thrown
#endif
        }
    }

无论我们是否定义TARGET_AS_TYPE 测试总是抛出异常,第二行包含#if#elseif阻止 。 我认为这是因为TypeRuntimeType,但我无法定义它。 那么, 如何纠正它(在GetTypeImpl中)并让它始终在没有条件编译的情况下工作

以下方式受到限制或我已完成但没有效果。

  • 使用BindingFlags.FlattenHierarchy - 不工作
  • 通用MyClass<T>声明 - 无法正常工作
  • 不要使用MyClass实例扭曲类型或对象 - 你一定是在开玩笑......

1 个答案:

答案 0 :(得分:3)

请考虑以下代码:

Abc a = new Abc { Name = "a" };

Type t = a.GetType();

BindingFlags staticField = BindingFlags.Static | 
                           BindingFlags.Public | 
                           BindingFlags.GetField;
BindingFlags instanceProperty = BindingFlags.Instance | 
                                BindingFlags.Public | 
                                BindingFlags.GetProperty;

//prints a
t.InvokeMember("Name", instanceProperty, default(Binder), a, null);
//prints wtf
t.InvokeMember("AbcName", staticField, default(Binder), a, null);
//throws an exception as there is no member FullName in MyClass
t.InvokeMember("FullName", instanceProperty, default(Binder), a, null);

Type tt = t.GetType();
//prints t.FullName, that is YourNamespace.Abc
tt.InvokeMember("FullName", instanceProperty, default(Binder), t, null);

它显示了你IMO所拥有的问题。您无法通过反映通过描述类Type的{​​{1}}类型的对象访问类Type的成员,因为MyClass没有这些成员。

您需要使用描述类MyClass的{​​{1}}对象(即Type)通过反射访问其成员(此处为Type)并传递类型为{的对象{1}}将课程a.GetType().GetType()描述为FullName


根据评论,我想在Type类型的对象上发布相同的示例:

MyClass