Dynamically Get and Set Properties on an EF Core Model

280 Views Asked by At

I'm learning C# and trying to find out how I can have a common method for updating different addresses that inherit from Address, and have an address type discriminator - PhysicalAddress and MailingAddress.

The example shows what I'd like to do if I could array access properties on models like you would in TypeScript. It indicates what I'm trying to do and have accomplished using two methods, but I haven't been able to figure out the way to achieve this in C#.

Any help, direction, or URL for referencing would be great. If this is not a good way to set up an update what would a properly single method update that would work with PerformUpdate.

// Example of an actual update method:
public async Task<int> PerformUpdate(User user, User updateUser) {
  UpdateAddress(user, updateUser.PhysicalAddress);
  UpdateAddress(user, updateUser.MailingAddress);

  return await _context.SaveChangesAsync();
}

// Example of what I would like to achieve:
private void UpdateAddress(User user, Address newAddress)
{
    // Currently would be: PhysicalAddress or MailingAddress
    var addressType = newAddress.GetType().ToString();

    // Dynamically access the address on the user based on the address type
    Address oldAddress = user[addressType];
    
    // Remove the old and add the new
    if(oldAddress != null) {
        _context.Addresses.Remove(oldAddress);
    }

    user[addressType] = newAddress;
}
1

There are 1 best solutions below

0
ekke On

I would look at the use case for this first, unless you have to support a truly huge number of classes it's probably better to create setters explicitly for each class you wish to support, for example with the is keyword. However, since you asked, we can abuse reflection to achieve this like so:

class Program
    {
        static void Main(string[] args)
        {
            var address = new PhysicalAddress();
            var user = new User();
            
            // this will set user.Address1 to address
            SetAddress(user, address);

        }

        public static void SetAddress(User user, Address newAddress)
        {
            var fields = typeof(User).GetFields();

            foreach (var fieldInfo in fields)
            {
                if (fieldInfo.FieldType == newAddress.GetType())
                {
                    fieldInfo.SetValue(user, newAddress);
                }
            }
        }

        
    }

    class User
    {
        public PhysicalAddress Address1;
        public WorkAdress Address2;
    }

    class Address
    {

    }

    class PhysicalAddress: Address
    {

    }

    class WorkAdress: Address
    {

    }
```