c# - 序列化 TypeBuilder 列表

标签 c# web-services wcf

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

我正在尝试根据从数据库返回的信息创建一个类型,用数据构建一个类型列表,然后将其发回。

但是,我得到了一个

Type 'MyDynamicType' with data contract name 'MyDynamicType:http://schemas.datacontract.org/2004/07/' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer. error in the trace viewer.

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

Type Builder类代码来自 How to dynamically create a class in C#?有非常小的修改。 (即分离创建类型和实例创建。)

网络服务端点

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

网络服务端点代码

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);
    }

}

提前致谢。

最佳答案

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

关于c# - 序列化 TypeBuilder 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38516046/

相关文章:

c# - 在 C# 中避免 namespace 和类型名称冲突的准则是什么?

c# - 在保护 WCF 服务方面需要帮助

wcf - 是否可以从VS2010插件刷新WCF服务引用?

c# - MVC Entity Framework 将一列作为数组

c# - 从 C# 中的字节数组中删除尾随空值

c# - 为什么在 AutoMapper 中会出现意外映射?

java - 是在 esb 内部还是在 esb 外部部署 web 服务

java - 在Web服务上写入和读取文件(axis2 + tomcat 7)

rest - 如何将 PowerShell 调用 webrequest 与 Windows 身份验证和用户名\密码一起使用

wcf - 以编程方式添加端点