System.Linq.Dynamic.Core icon indicating copy to clipboard operation
System.Linq.Dynamic.Core copied to clipboard

DynamicClass Merging base class properties with additional classes

Open frankiDotNet opened this issue 4 years ago • 2 comments

Hi,

I have this example classes:

   public class PayData
   {
      public string Article { get; set; }
      public int Id { get; set; }
      public string Name { get; set; }
      public double Fee{ get; set; }
   }
   public class Customer
   {
      public string Name { get; set; }
      public int Age { get; set; }
      public List<PayData> Paid { get; set; }
   }

Now I would like to create a dynamic object that has all properties of Customer and add additional properties, in my case different items of the Paid-list property.

// Fill with custom data...
var customer = new Customer()
            {
               Age = 18,
               Name = "Hans",
               Paid = new List<PayData>()
               {
                  new PayData()
                  {
                     Name = "Cola",
                     Article = "213456",
                     Fee = 1.55,
                     Id = 1
                  },
                  new PayData()
                  {
                     Name = "Pepsi",
                     Article = "d3434",
                     Fee = 1.25,
                     Id = 2
                  },
                  new PayData()
                  {
                     Name = "Wasser",
                     Article = "4213",
                     Fee = 0.8,
                     Id = 3
                  }
               }
            };

// The definition would be:
dynamic dynObj = new
{
      Article  = customer.Article,
      Id  = customer.Id,
      Name  = customer.Name ,
      Fee  = customer.Fee ,
      Paid  = customer.Paid,
      Item = customer.Paid.FirstOrDefault(x => x.Name == "cola")
   };

Now I would like to do this in dynamic way using the DynamicClass:

public static DynamicClass GenerateMergedDynamicClass(object obj, IDictionary<string, Tuple<Type, object>> additionalProperties)
      {
         var propList = new List<DynamicProperty>();
         var objType = obj?.GetType();
         var objectProperties = objType?.GetProperties();
         if (objectProperties != null)
         {
            propList.AddRange(objectProperties.Select(x => new DynamicProperty(x.Name, x.PropertyType)));
         }

         if (additionalProperties != null)
         {
            foreach (var additionalProperty in additionalProperties)
            {
               if (propList.All(x => x.Name != additionalProperty.Key))
               {
                  propList.Add(new DynamicProperty(additionalProperty.Key, additionalProperty.Value.Item1));
               }
            }
         }

         Type type = DynamicClassFactory.CreateType(propList);
         
         var dynamicClass = Activator.CreateInstance(type) as DynamicClass;
         if (dynamicClass == null)
         {
            return null;
         }
         if (objectProperties != null)
         {
            var objAccessor = TypeAccessor.Create(objType);
            for (int i = 0; i < objectProperties.Length; i++)
            {
               dynamicClass.SetDynamicPropertyValue(objectProperties[i].Name, objAccessor[obj, objectProperties[i].Name]);
            }
         }
         if (additionalProperties != null)
         {
            foreach (var additionalProperty in additionalProperties)
            {
              // ------------ Here the Exception is thrown!!!! ------------------------------
               dynamicClass.SetDynamicPropertyValue(additionalProperty.Key, additionalProperty.Value.Item2);
            }
         }

         return dynamicClass;
      }
               var aditionalObject = customer.Paid.FirstOrDefault(x => x.Name == "cola");
               var dynObj = DynamicObjectExtension.GenerateMergedDynamicClass(customer,
                  new Dictionary<string, Tuple<Type, object>>() {{"Item", new Tuple<Type, object>(typeof(PayData), aditionalObject)}});
               
               var dynExpr = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, dynObj.GetType(), typeof(object), "Name + \" - \" + Item.Article ");
               var resultObject = (dynExpr.Compile()).DynamicInvoke(dynObj);

I get the exception when setting the 'Item' property with SetDynamicPropertyValue. If I call the GetProperties method of the DynamicClass type, I get two properties with the name Item.

frankiDotNet avatar Aug 20 '20 10:08 frankiDotNet

Hello @Franki1986,

Do you think you could provide a project that compiles which we can run?

It will help my developer investigate the issue more efficiently.

Even if you believe you have provided enough information, we cannot count anymore the number of times someone believes it also, and a third-party package or piece of code was missing, and we were losing hours to reproduce it instead of spending those hours to fix it.

You can send it to: [email protected] if you need to keep the source private Best Regards,

Jonathan


Performance Libraries context.BulkInsert(list, options => options.BatchSize = 1000); Entity Framework ExtensionsEntity Framework ClassicBulk OperationsDapper Plus

Runtime Evaluation Eval.Execute("x + y", new {x = 1, y = 2}); // return 3 C# Eval FunctionSQL Eval Function

JonathanMagnan avatar Aug 20 '20 14:08 JonathanMagnan

@frankiDotNet Is this issue still relevant to you, if so, can you provide a full working dotnetfiddle?

Else I'll close this.

StefH avatar Apr 13 '24 19:04 StefH