What is the best way to merge two objects during runtime using C#?

后端 未结 7 520
野的像风
野的像风 2021-02-06 10:18

I have two objects and I want to merge them:

public class Foo
{
    public string Name { get; set; }
}

public class Bar
{
    public Guid Id { get; set; }
    p         


        
相关标签:
7条回答
  • 2021-02-06 10:59

    Unfortunately, this is not something you can do easily. The best you can do is to create an anonymous type as part of a LINQ query, but that will have local scope only, and so will only be good for you in the method wherein you make it.

    When .NET 4 comes out, there's a new Dynamic Runtime Library that might help you out.

    0 讨论(0)
  • 2021-02-06 11:05

    UNTESTED, but using the Reflection.Emit API, something like this should work:

    public Type MergeTypes(params Type[] types)
    {
        AppDomain domain = AppDomain.CurrentDomain;
        AssemblyBuilder builder = 
            domain.DefineDynamicAssembly(new AssemblyName("CombinedAssembly"),
            AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder moduleBuilder = builder.DefineDynamicModule("DynamicModule");
        TypeBuilder typeBuilder = moduleBuilder.DefineType("CombinedType");
        foreach (var type in types)
        {
            var props = GetProperties(type);
            foreach (var prop in props)
            {
                typeBuilder.DefineField(prop.Key, prop.Value, FieldAttributes.Public);
            }
        }
    
        return typeBuilder.CreateType();
    
    
    }
    
    private Dictionary<string, Type> GetProperties(Type type)
    {
        return type.GetProperties().ToDictionary(p => p.Name, p => p.PropertyType);
    }
    

    USAGE:

    Type combinedType = MergeTypes(typeof(Foo), typeof(Bar));
    
    0 讨论(0)
  • 2021-02-06 11:11

    Aside from the question "Why", the only way I can think to take two objects, one known and one unknown, and combine them into a new type would be to use Reflection.Emit to generate a new type at runtime.

    There are examples on MSDN. You would have to determine weather you wanted to merge fields that had the same name or have the known type supersede the unknown type.

    As far as I can tell, there is no way to do this in LINQ.

    Since all you're interested in is Properties it should be pretty easy to use this article as an example. Leave out the il for creating methods and you're good to go.

    0 讨论(0)
  • 2021-02-06 11:12

    If you don't mind them being grouped rather than merged:

    public class FooEx<T>
    {
        public Foo Foo { get; set; }
        public T Ex { get; set; }
    }
    
    0 讨论(0)
  • 2021-02-06 11:12

    If you can add a method to the metadata class you could do something like the following

    public class Foo
    {
        public string Name { get; set; }
        public void SerializeWithMetadata(Bar bar)
        {
           var obj = new {
                           Name = this.Name,
                           Guid = bar.Guid,
                           Property1 = Bar.Property1
                          }
           //Serialization code goes here
        }
    }
    
    public class Bar
    {
        public Guid Id { get; set; }
        public string Property1 { get; set; }
        public string Property2 { get; set; }
        public string Property3 { get; set; }
        public string Property4 { get; set; }
    }
    

    I'm not sure I would recommend this exact approach I mainly left it here to display anonymous types as a possible option that might be worth exploring

    0 讨论(0)
  • 2021-02-06 11:19

    As others have pointed out, there is no way to "merge" them (if you're thinking of a select * with multiple tables in SQL, for example). Your closest analog would be taking the route that Zxpro has provided and "group" them in a generic class.

    What, exactly, would you want to accomplish with "merging" them, though? Declaring the properties explicitly would have the biggest convenience effect on writing code and compile-time safety, but if you can't specify a type then there's no opportunity for that. If you're just looking for a generic "property bag" container, then an existing data structure, such as a Dictionary<T,T> or Hashtable should be able to handle that.

    0 讨论(0)
提交回复
热议问题