创建一个新的匿名类型实例。

5
我试图创建一个匿名类型的实例,看起来像这样:
new { Channel = g.Key.Channel, Comment = g.Key.Comment, Count = g.Count() }

在暗处,.NET创建了一个具有三个参数的构造函数的AnonymousType:String,String,Int32
为了创建这个匿名类型T的新实例,我执行以下操作:
object[] args = new object[3];
args[0] = "arg1";
args[1] = "arg2";
args[2] = 200;
(T)Activator.CreateInstance(typeof(T), args);

.NET 报错:

额外信息: 在“<>f__AnonymousType2`3[[System.String, ...],[System.String, ...],[System.Int32, ...]]”中找不到构造函数。

我不知道为什么 CreateInstance 会试图调用如 [[],[],[]] 的构造函数!

范围

实际的范围有点难以解释:

我创建了一个 Linq 提供程序。该提供程序将 Linq 语句转换为服务器方法。当我收到 JSON 信息时,我需要将此信息投影到用户指定的任何类型。在这种情况下:

var enumerable = UIContainer.UIController.Instance.getDigitalInputs()
    .GroupBy(di => new { Channel = di.Channel, Comment = di.Comment })
    .Select(g => new { Channel = g.Key.Channel, Comment = g.Key.Comment, Count = g.Count() });

因此,我需要将每个json项目投影到新 { Channel = g.Key.Channel, Comment = g.Key.Comment, Count = g.Count() }。最后,我需要创建这个匿名类型的实例。

所以:

// make the HTTP request
IRestResponse response = (IRestResponse) this.client.CallApi(path, Method.GET, queryParams, postBody, headerParams, formParams, fileParams, authSettings);

if (((int)response.StatusCode) >= 400) {
    throw new ApiException (response.StatusCode, "Error calling Search: " + response.Content, response.Content);
}

Newtonsoft.Json.Linq.JArray feeds = Newtonsoft.Json.Linq.JArray.Parse(response.Content);
if (feeds.Any())
{
     PropertyDescriptorCollection dynamicProperties = TypeDescriptor.GetProperties(feeds.First());
     foreach (dynamic feed in feeds)
     {
         object[] args = new object[dynamicProperties.Count];
         int i = 0;
         foreach (PropertyDescriptor prop in dynamicProperties)
         {
             args[i++] = prop.GetValue(feed);
         }
         //args[0] = "";
         //args[1] = "";
         //args[2] = 2;

         yield return (T)Activator.CreateInstance(typeof(T), args);
    }
}

你为什么要这样做?如果你需要随意创建实例,只需使用一个命名类型即可。 - Luaan
无论是哪个“匿名类型”。 - Jordi
你正在尝试从数组中创建一个类型? - Baahubali
不,那些是构造函数参数。@user1490835 - Patrick Hofman
1个回答

3

不确定您从何处获得T,但如果您使用先前变量中的匿名类型,则该代码可以正常工作:

var x = new { Channel = "Channel", Comment = "Comment", Count = 1 };

object[] args = new object[3];
args[0] = "arg1";
args[1] = "arg2";
args[2] = 200;
var y = Activator.CreateInstance(x.GetType(), args);

(回复Luaan:.NET使用一个构造函数来创建匿名类型,参见IL代码:)
.method public hidebysig specialname rtspecialname 
        instance void  .ctor(!'<Channel>j__TPar' Channel,
                             !'<Comment>j__TPar' Comment,
                             !'<Count>j__TPar' Count) cil managed

是的。我刚意识到它可以使用一个简单的 object["a", "b", 200] 来工作。问题可能来自于由Newton.Json库创建的 dynamic 对象。我已经在帖子上添加了 json.net 标签。 - Jordi
仍然不知道T是什么。 - Patrick Hofman
T 是任何匿名类型。 - Jordi
var newAnonimoysTypeInstance = x.GetType().GetConstructors().First().Invoke(args);变量newAnonimoysTypeInstance等于x的类型获取构造函数后调用第一个构造函数并传入参数。 - Denis Fedak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接