Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#使用反射创建结构_C#_Reflection - Fatal编程技术网

C#使用反射创建结构

C#使用反射创建结构,c#,reflection,C#,Reflection,我目前正在编写一些代码,使用c#中的反射将常规对象保存到XML 问题是,当在一些对象中读回XML时,这些对象是结构,我无法确定如何初始化结构。对于一个我可以使用的类 ConstructorInfo constructor = SomeClass.GetConstructor(Type.EmptyTypes); 但是,对于结构,没有不带参数的构造函数,因此上面的代码将构造函数设置为null。我也试过了 SomeStruct.TypeInitializer.Invoke(null) 但这会引发m

我目前正在编写一些代码,使用c#中的反射将常规对象保存到XML

问题是,当在一些对象中读回XML时,这些对象是结构,我无法确定如何初始化结构。对于一个我可以使用的类

ConstructorInfo constructor = SomeClass.GetConstructor(Type.EmptyTypes);
但是,对于结构,没有不带参数的构造函数,因此上面的代码将构造函数设置为null。我也试过了

SomeStruct.TypeInitializer.Invoke(null)

但这会引发memberaccessexception。谷歌没有给出有希望的点击率。任何帮助都将不胜感激。

如果值是结构,那么它们很可能是不可变的-因此您不希望调用无参数构造函数,而是调用将适当的值作为构造函数参数的构造函数

如果结构不是不可变的,那么尽可能快地逃离它们,如果可以的话。。。但是如果您确实必须这样做,那么就使用
Activator.CreateInstance(SomeClass)
。但是,在使用反射来设置值类型的属性或字段时,必须非常小心——如果不小心,最终会创建一个副本,更改该副本上的值,然后将其丢弃。我怀疑如果你一直使用盒装版本,你会没事的:

using System;

// Mutable structs - just say no...
public struct Foo
{
    public string Text { get; set; }
}

public class Test
{
    static void Main()
    {
        Type type = typeof(Foo);

        object value = Activator.CreateInstance(type);
        var property = type.GetProperty("Text");
        property.SetValue(value, "hello", null);

        Foo foo = (Foo) value;
        Console.WriteLine(foo.Text);
    }
}

只需添加-withimmutable结构,您可能需要对构造函数进行参数匹配。不幸的是,当存在多个构造时,这是很棘手的,特别是因为某些类型有一个单独的静态“Create”方法而不是公共构造函数。但是假设您已经完成了匹配,您仍然可以使用
Activator.CreateInstance

    Type type = typeof(Padding); // just an example
    object[] args = new object[] {1,2,3,4};
    object obj = Activator.CreateInstance(type, args);
然而,选择构造函数的代码(上面有3…)并不容易。您可以说“选择最复杂的”,然后尝试将参数名与属性名匹配(不区分大小写)

一个天真的例子:

static void Main() {
    Dictionary<string, object> propertyBag =
        new Dictionary<string, object>();
    // these are the values from your xml
    propertyBag["Left"] = 1;
    propertyBag["Top"] = 2;
    propertyBag["Right"] = 3;
    propertyBag["Bottom"] = 4;
    // the type to create
    Type type = typeof(Padding);

    object obj = CreateObject(type, propertyBag);

}
static object CreateObject(Type type, IDictionary<string,object> propertyBag)
{
    ConstructorInfo[] ctors = type.GetConstructors();
    // clone the property bag and make it case insensitive
    propertyBag = new Dictionary<string, object>(
        propertyBag, StringComparer.OrdinalIgnoreCase);
    ConstructorInfo bestCtor = null;
    ParameterInfo[] bestParams = null;
    for (int i = 0; i < ctors.Length; i++)
    {
        ParameterInfo[] ctorParams = ctors[i].GetParameters();
        if (bestCtor == null || ctorParams.Length > bestParams.Length)
        {
            bestCtor = ctors[i];
            bestParams = ctorParams;
        }
    }
    if (bestCtor == null) throw new InvalidOperationException(
         "Cannot create - no constructor");
    object[] args = new object[bestParams.Length];
    for (int i = 0; i < bestParams.Length; i++)
    {
        args[i] = propertyBag[bestParams[i].Name];
        propertyBag.Remove(bestParams[i].Name);
    }
    object obj = bestCtor.Invoke(args);
    // TODO: if we wanted, we could apply any unused keys in propertyBag
    // at this point via properties
    return obj;
}
static void Main(){
字典属性标签=
新字典();
//这些是xml中的值
propertyBag[“左”]=1;
propertyBag[“顶部”]=2;
propertyBag[“Right”]=3;
propertyBag[“底部”]=4;
//要创建的类型
类型=类型(填充);
object obj=CreateObject(类型,propertyBag);
}
静态对象CreateObject(类型,IDictionary propertyBag)
{
ConstructorInfo[]ctors=type.GetConstructors();
//克隆属性包并使其不区分大小写
propertyBag=新字典(
propertyBag,StringComparer.OrdinalingOrecase);
ConstructorInfo bestCtor=null;
ParameterInfo[]bestParams=null;
for(int i=0;ibestParams.Length)
{
最佳系数=系数[i];
最佳参数=最佳参数;
}
}
如果(bestCtor==null)抛出新的InvalidOperationException(
“无法创建-无构造函数”);
object[]args=新对象[bestParams.Length];
对于(int i=0;i
CreateInstance将无法帮助您处理没有明确定义构造函数的结构

FormatterServices.GetUninitializedObject(Type type);

这在空白结构中实现了这个技巧。

在epic线程中发布。。。另外,请投票选择简洁明了的答案。问题是,现在Activator.CreateInstance返回的是RuntimeType,而不是我要求的类型:(这意味着GetFields什么也不返回。@Marcel:听起来你应该问一个新问题。My bad;试图找到类型是问题所在,而不是这个。如果我不能解决这个问题,我将发布一个问题。如果结构是
byte
?因为它是不可变的,我不能在创建实例后设置它的值。如何设置它的值ing
Activator
?不正确。如果您的结构没有构造函数,Activator.CreateInstance可以正常工作。