正在序列化TypeBuilder列表

本文关键字:列表 TypeBuilder 序列化 | 更新日期: 2023-09-27 17:58:04

我正在创建一个WCF Web服务。

我正试图根据数据库中返回的信息创建一个类型,用数据构建一个类型列表,并将其发回。

然而,我得到了

数据协定名称为"MyDynamicType:http://schemas.datacontract.org/2004/07/不应为"。考虑使用DataContractResolver或将任何未知类型静态添加到已知类型列表中,例如,使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表。跟踪查看器中出现错误。

正在研究异常。建议将该类型添加到[KnownTypes(Type)]中。如何对以这种方式创建的类型执行此操作?

类型生成器类代码来自如何在C#中动态创建类?经过非常小的修改。(即分离创建类型和实例创建。)

Web服务端点

   [OperationContract]
        [WebInvoke(Method = "GET",
            UriTemplate = "/DB/{Q}")]
        List<object> DB(string Q);

Web服务端点代码

public List<object> DB(string Q)
    {
        List<object> rows = DLL.DB.RunQuery(IQueries.LoadQuery(Q));
        return rows;
    }

运行查询方法

public static List<object> RunQuery(string query)
        {            
            using (SqlConnection connection = new SqlConnection(ConnectionString))
            {
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;
                    command.CommandText = query;
                    connection.Open();
                    using (SqlDataAdapter da = new SqlDataAdapter(command))
                    {
                        DataTable dt = new DataTable();
                        da.Fill(dt);
                        Dictionary<string, Type> columns = new Dictionary<string, Type>();
                        foreach (DataColumn dc in dt.Columns)
                        {
                            columns.Add(dc.ColumnName, dc.DataType);
                        }
                        Type customType = MyTypeBuilder.CreateNewObject(columns);                                                
                        List <object> rows = new List<object>();
                        foreach (DataRow dr in dt.Rows)
                        {
                            List<object> row = new List<object>();
                            foreach (DataColumn col in dt.Columns)
                            {
                                object customInstance = MyTypeBuilder.CreateObjectInstance(customType);
                                PropertyInfo pi = customType.GetProperty(col.ColumnName);
                                pi.SetValue(customInstance, dr[col]);
                                row.Add(customInstance);                                
                            }
                            rows.Add(row);
                        }
                        return rows;
                    }
                }
            }
        }

我的类型生成器

public class MyTypeBuilder
{        
    public static object CreateObjectInstance(Type myType)
    {
        var myObject = Activator.CreateInstance(myType);
        return myObject;
    }
    public static Type CreateNewObject(Dictionary<string,Type> values)
    {
        var myType = CompileResultType(values);            
        return myType;
    }
    public static Type CompileResultType(Dictionary<string, Type> values)
    {
        TypeBuilder tb = GetTypeBuilder();
        ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
        // NOTE: assuming your list contains Field objects with fields FieldName(string) and FieldType(Type)
        foreach (var field in values)
            CreateProperty(tb, field.Key, field.Value);
        Type objectType = tb.CreateType();
        return objectType;
    }
    private static TypeBuilder GetTypeBuilder()
    {
        var typeSignature = "MyDynamicType";
        var an = new AssemblyName(typeSignature);
        AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
        TypeBuilder tb = moduleBuilder.DefineType(typeSignature
                            , TypeAttributes.Public |
                            TypeAttributes.Class |
                            TypeAttributes.AutoClass |
                            TypeAttributes.AnsiClass |
                            TypeAttributes.BeforeFieldInit |
                            TypeAttributes.AutoLayout |
                            TypeAttributes.Serializable
                            , null);
        return tb;
    }
    private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
    {
        FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
        PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
        MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
        ILGenerator getIl = getPropMthdBldr.GetILGenerator();
        getIl.Emit(OpCodes.Ldarg_0);
        getIl.Emit(OpCodes.Ldfld, fieldBuilder);
        getIl.Emit(OpCodes.Ret);
        MethodBuilder setPropMthdBldr =
            tb.DefineMethod("set_" + propertyName,
              MethodAttributes.Public |
              MethodAttributes.SpecialName |
              MethodAttributes.HideBySig,
              null, new[] { propertyType });
        ILGenerator setIl = setPropMthdBldr.GetILGenerator();
        Label modifyProperty = setIl.DefineLabel();
        Label exitSet = setIl.DefineLabel();
        setIl.MarkLabel(modifyProperty);
        setIl.Emit(OpCodes.Ldarg_0);
        setIl.Emit(OpCodes.Ldarg_1);
        setIl.Emit(OpCodes.Stfld, fieldBuilder);
        setIl.Emit(OpCodes.Nop);
        setIl.MarkLabel(exitSet);
        setIl.Emit(OpCodes.Ret);
        propertyBuilder.SetGetMethod(getPropMthdBldr);
        propertyBuilder.SetSetMethod(setPropMthdBldr);
    }
}

提前谢谢。

正在序列化TypeBuilder列表

也许您可以拥有一个所有动态类型都继承自的基类。然后,您可以将基类作为您放入knownTypes装饰器中的基类。

这里有一些简单的代码可以让你开始,

[KnownType(typeof(YourSpecialObject))]
    [DataContract]
    public abstract class BusinessObjectInfo
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public Byte[] Version { get; set; }
    }

现在你的特殊对象

[DataContract]
    public class YourSpecialObject: BusinessObjectInfo

现在,WCF应该解析KnownTypes。至于学习这一点的方法,Zombie Explorer将提供大量关于IOC/WWCF/PRISM for.NET的信息以下是WCF的一个相当全面的示例链接,http://www.codeproject.com/Articles/474212/Zombie-Explorer-An-n-tier-application-from-top-to

我会用一种完全不同的、更简单的方式来做。我的解决方案基于以下推理:

  1. 您的动态类型,即MyDynamicType,是基于数据创建的表格结构->
  2. MyDynamicType的实例实际上是行->
  3. MyDynamicType的实例实际上是键/值集合->
  4. 您不必创建动态类型MyDynamicType。只要用一本简单的字典就足够了。此字典中的键将是列的名称,值将对应于单元格(列的值)

据我所知,WCF使用DataContractJsonSerializer将数据序列化为JSON格式,我非常确信它能正确处理字典。也请阅读这篇文章。

您也可以使用另一个序列化程序,而不是默认的序列化程序,例如NewtonsoftJson.Net序列化程序。看看这个或这个问题。

最后,为什么要使用WCF来创建类似REST的API?我认为WebApi更容易使用,除非你有一些特定的理由使用WCF。

因此,不幸的是,即使这里的每个人都向我提供了所有优秀的信息,我也无法真正让TypeBuilder正常工作。

然而,我尝试使用TypeBuilder的原因是我的数据没有像我希望的那样格式化为JSON

{key:dataname,value:value}

当我真正想要的是

{dataname:value}

使用JSON和其他一些经验完成了Web服务。我知道Type会符合这种布局。不幸的是,数据是未知的,可能会随时更改,web服务不得不处理这一问题(不幸的要求)。

尽管我无法让TypeBuilder按我希望的方式工作。我能够使用Newtonsoft.Json并在服务器尝试为我序列化之前从字典中序列化数据,从而获得所需的结果。

感谢大家的帮助。我学到了一些有趣的、很棒的新东西,我可能会在其他项目中使用。

感谢