0

I'm working on a method that dynamically copies variables of the same name and type (not necessarily from the same class). I don't want to blindly copy everything because an admin of the site has that ability while a user doesn't. For example, here are some of the event objects:

public class Event
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime EventDate { get; set; }
    public int Organization { get; set; }
    public string Location { get; set; }
    public int SpotsAvailable { get; set; }
    public int CreatedBy { get; set; }
    public DateTime CreatedDate { get; set; }
    public int ModifiedBy { get; set; }
    public DateTime ModifiedDate { get; set; }
    public int ApprovedBy { get; set; }
    public DateTime ApprovedDate { get; set; }
    public bool AutomaticallyApproved { get; set; }
}

What I want to do is have a generic method that only clones the objects I want, ignoring an array of variable names that I want to be left blank or the property's default. Based off of this post I created a method that copies all fields that are named the same and have the same property type and everything works great. Now I want to add a line (if(ignoreObjects.Contains(srcProp.Name))) that can check if the ignore array contains the current property:

 public void Clone(ref object destination, object source, object[] ignoreObjects)
    {
        // Getting the Types of the objects
        Type typeDest = destination.GetType();
        Type typeSrc = source.GetType();

        // Iterate the Properties of the source instance and  
        // populate them from their desination counterparts  
        PropertyInfo[] srcProperties = typeSrc.GetProperties();
        foreach (PropertyInfo srcProp in srcProperties)
        {
            if(ignoreObjects.Contains(srcProp.Name))
            {
                continue;
            }
            PropertyInfo targetProperty = typeDest.GetProperty(srcProp.Name);
            if (targetProperty == null)
            {
                continue;
            }
            if (!targetProperty.CanWrite)
            {
                continue;
            }
            if (targetProperty.GetSetMethod(true) != null && targetProperty.GetSetMethod(true).IsPrivate)
            {
                continue;
            }
            if ((targetProperty.GetSetMethod().Attributes & MethodAttributes.Static) != 0)
            {
                continue;
            }
            if (!targetProperty.PropertyType.IsAssignableFrom(srcProp.PropertyType))
            {
                continue;
            }

            targetProperty.SetValue(destination, srcProp.GetValue(source, null), null);
        }
    }

I would ideally call the method above like this:

 Clone(ref newEvent, eventInfo, { eventInfo.ApprovedBy, eventInfo.ApprovedDate, eventInfo.Organization, eventInfo.SpotsAvailable } );

Where this would copy all event information from "eventInfo" into "newEvent", ignoring the fields ApprovedBy, ApprovedDate, Organization, and SpotsAvailable.

Is it possible to send a list/array of variables to an ignored array? I can certainly add a "nameof" before each variable to create a string array (ex: nameof(eventInfo.ApprovedBy) ) but I would prefer to just reference the class properties themselves to reduce code.

I've previously used AutoMapper but want to learn if this is possible without any 3rd party tools.

Community
  • 1
  • 1
Slippery Pete
  • 526
  • 5
  • 10

1 Answers1

0

You have to use object to transfer property name or PropertyInfo, you can not pass property value then detect what property it is. You should use params keyword:

public void Clone(object destination, object source, params String[] ignoreObjects)

And call the method:

Clone(newEvent, eventInfo, property1, property2, property3, ...);

You pass the object then you don't need ref keyword.

Nam Tran
  • 643
  • 4
  • 14