Advertisement
leo1553

Dynamic Classes

Apr 5th, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.06 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Dynamic;
  4.  
  5. namespace DynamicTypes.Code.Dynamic {
  6.     public class DynamicClass : DynamicObject {
  7.         protected delegate void GetMemberDelegate(GetMemberBinder binder, out object result);
  8.         protected delegate void SetMemberDelegate(SetMemberBinder binder, object value);
  9.  
  10.         protected readonly Dictionary<string, DynamicField> fields;
  11.         protected readonly bool allowUnsetFields;
  12.         protected readonly GetMemberDelegate getMember;
  13.         protected readonly SetMemberDelegate setMember;
  14.  
  15.         public bool AllowUnsetFields => allowUnsetFields;
  16.  
  17.         public DynamicClass(bool allowUnsetFields = false) {
  18.             fields = new Dictionary<string, DynamicField>();
  19.  
  20.             this.allowUnsetFields = allowUnsetFields;
  21.             if(allowUnsetFields) {
  22.                 getMember = GetMember_Allowed;
  23.                 setMember = SetMember_Allowed;
  24.             }
  25.             else {
  26.                 getMember = GetMember_NotAllowed;
  27.                 setMember = SetMember_NotAllowed;
  28.             }
  29.         }
  30.         public DynamicClass(List<DynamicField> fields, bool allowUnsetFields = false) : this(allowUnsetFields) {
  31.             foreach(DynamicField field in fields)
  32.                 this.fields.Add(field.Name, field);
  33.         }
  34.        
  35.         // Get Fields
  36.         public override IEnumerable<string> GetDynamicMemberNames() {
  37.             return fields.Keys;
  38.         }
  39.  
  40.         public IEnumerable<DynamicField> GetDynamicFields() {
  41.             foreach(var pair in fields)
  42.                 yield return pair.Value;
  43.         }
  44.  
  45.         // Field Add and Remove
  46.         public void AddField(DynamicField field) {
  47.             if(fields.ContainsKey(field.Name))
  48.                 throw new InvalidOperationException("Field already exists: " + field.Name);
  49.             fields.Add(field.Name, field);
  50.         }
  51.  
  52.         public void RemoveField(DynamicField field) {
  53.             if(!fields.ContainsKey(field.Name))
  54.                 throw new InvalidOperationException("Invalid field: " + field.Name);
  55.             fields.Remove(field.Name);
  56.         }
  57.  
  58.         // Field Get and Set
  59.         public override bool TryGetMember(GetMemberBinder binder, out object result) {
  60.             getMember(binder, out result);
  61.             return true;
  62.         }
  63.  
  64.         public override bool TrySetMember(SetMemberBinder binder, object value) {
  65.             setMember(binder, value);
  66.             return true;
  67.         }
  68.  
  69.         // Handlers
  70.         protected void GetMember_Allowed(GetMemberBinder binder, out object result) {
  71.             string field = binder.Name;
  72.             if(!fields.ContainsKey(field)) {
  73.                 result = null;
  74.                 return;
  75.             }
  76.  
  77.             Type declaringType = fields[field].Type;
  78.             if (binder.ReturnType != declaringType && !declaringType.IsSubclassOf(binder.ReturnType))
  79.                 throw new InvalidOperationException("Invalid type for field: " + field);
  80.  
  81.             result = fields[field].Value;
  82.         }
  83.  
  84.         protected void GetMember_NotAllowed(GetMemberBinder binder, out object result) {
  85.             string field = binder.Name;
  86.             if (!fields.ContainsKey(field))
  87.                 throw new InvalidOperationException("Invalid field: " + field);
  88.             Type declaringType = fields[field].Type;
  89.             if (binder.ReturnType != declaringType && !declaringType.IsSubclassOf(binder.ReturnType))
  90.                 throw new InvalidOperationException("Invalid type for field: " + field);
  91.  
  92.             result = fields[field].Value;
  93.         }
  94.  
  95.         protected void SetMember_Allowed(SetMemberBinder binder, object value) {
  96.             string field = binder.Name;
  97.             if(!fields.ContainsKey(field)) {
  98.                 AddField(new DynamicField(field, value.GetType(), value));
  99.                 return;
  100.             }
  101.  
  102.             Type declaringType = fields[field].Type;
  103.             if (value.GetType() != declaringType && !value.GetType().IsSubclassOf(declaringType))
  104.                 throw new InvalidOperationException("Invalid type for field: " + field);
  105.  
  106.             fields[field].Value = value;
  107.         }
  108.  
  109.         protected void SetMember_NotAllowed(SetMemberBinder binder, object value) {
  110.             string field = binder.Name;
  111.             if (!fields.ContainsKey(field))
  112.                 throw new InvalidOperationException("Invalid field: " + field);
  113.             Type declaringType = fields[field].Type;
  114.             if (value.GetType() != declaringType && !value.GetType().IsSubclassOf(declaringType))
  115.                 throw new InvalidOperationException("Invalid type for field: " + field);
  116.  
  117.             fields[field].Value = value;
  118.         }
  119.     }
  120.  
  121.     public class DynamicField {
  122.         public string Name { get; private set; }
  123.         public Type Type { get; private set; }
  124.         public object Value { get; set; }
  125.  
  126.         public DynamicField(string name, Type type, object value = null) {
  127.             Name = name;
  128.             Type = type;
  129.             Value = value;
  130.         }
  131.     }
  132. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement