首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用反射创建结构的C#

使用反射创建结构的C#
EN

Stack Overflow用户
提问于 2009-06-17 05:57:38
回答 3查看 11.7K关注 0票数 15

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

问题是,当读回XML时,一些对象是结构,而我不知道如何初始化结构。对于一个我可以使用的类

代码语言:javascript
复制
ConstructorInfo constructor = SomeClass.GetConstructor(Type.EmptyTypes);

但是,对于结构,没有不带参数的构造函数,所以上面的代码将构造函数设置为null。我也试过了

代码语言:javascript
复制
SomeStruct.TypeInitializer.Invoke(null)

但是这会抛出一个成员访问异常。谷歌没有给出有希望的点击率。任何帮助都将不胜感激。

EN

回答 3

Stack Overflow用户

发布于 2009-06-17 05:59:38

如果值是结构,它们可能是不可变的-所以你不想调用一个无参数的构造函数,而是调用一个接受适当的值作为构造函数参数的构造函数。

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

代码语言:javascript
复制
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);
    }
}
票数 20
EN

Stack Overflow用户

发布于 2011-07-05 18:01:41

对于没有显式定义构造函数的结构,CreateInstance将帮不上忙。

代码语言:javascript
复制
FormatterServices.GetUninitializedObject(Type type);

这可以通过空结构来实现。

票数 7
EN

Stack Overflow用户

发布于 2009-06-17 07:16:40

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

代码语言:javascript
复制
    Type type = typeof(Padding); // just an example
    object[] args = new object[] {1,2,3,4};
    object obj = Activator.CreateInstance(type, args);

然而-选择构造函数的代码(上面有3个...)并不容易。您可以说“选择最复杂的”,然后尝试将参数名称与属性名称匹配(不区分大小写)……

一个天真的例子:

代码语言:javascript
复制
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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1005336

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档