Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Dynamic;
- namespace DynamicTypes.Code.Dynamic {
- public class DynamicClass : DynamicObject {
- protected delegate void GetMemberDelegate(GetMemberBinder binder, out object result);
- protected delegate void SetMemberDelegate(SetMemberBinder binder, object value);
- protected readonly Dictionary<string, DynamicField> fields;
- protected readonly bool allowUnsetFields;
- protected readonly GetMemberDelegate getMember;
- protected readonly SetMemberDelegate setMember;
- public bool AllowUnsetFields => allowUnsetFields;
- public DynamicClass(bool allowUnsetFields = false) {
- fields = new Dictionary<string, DynamicField>();
- this.allowUnsetFields = allowUnsetFields;
- if(allowUnsetFields) {
- getMember = GetMember_Allowed;
- setMember = SetMember_Allowed;
- }
- else {
- getMember = GetMember_NotAllowed;
- setMember = SetMember_NotAllowed;
- }
- }
- public DynamicClass(List<DynamicField> fields, bool allowUnsetFields = false) : this(allowUnsetFields) {
- foreach(DynamicField field in fields)
- this.fields.Add(field.Name, field);
- }
- // Get Fields
- public override IEnumerable<string> GetDynamicMemberNames() {
- return fields.Keys;
- }
- public IEnumerable<DynamicField> GetDynamicFields() {
- foreach(var pair in fields)
- yield return pair.Value;
- }
- // Field Add and Remove
- public void AddField(DynamicField field) {
- if(fields.ContainsKey(field.Name))
- throw new InvalidOperationException("Field already exists: " + field.Name);
- fields.Add(field.Name, field);
- }
- public void RemoveField(DynamicField field) {
- if(!fields.ContainsKey(field.Name))
- throw new InvalidOperationException("Invalid field: " + field.Name);
- fields.Remove(field.Name);
- }
- // Field Get and Set
- public override bool TryGetMember(GetMemberBinder binder, out object result) {
- getMember(binder, out result);
- return true;
- }
- public override bool TrySetMember(SetMemberBinder binder, object value) {
- setMember(binder, value);
- return true;
- }
- // Handlers
- protected void GetMember_Allowed(GetMemberBinder binder, out object result) {
- string field = binder.Name;
- if(!fields.ContainsKey(field)) {
- result = null;
- return;
- }
- Type declaringType = fields[field].Type;
- if (binder.ReturnType != declaringType && !declaringType.IsSubclassOf(binder.ReturnType))
- throw new InvalidOperationException("Invalid type for field: " + field);
- result = fields[field].Value;
- }
- protected void GetMember_NotAllowed(GetMemberBinder binder, out object result) {
- string field = binder.Name;
- if (!fields.ContainsKey(field))
- throw new InvalidOperationException("Invalid field: " + field);
- Type declaringType = fields[field].Type;
- if (binder.ReturnType != declaringType && !declaringType.IsSubclassOf(binder.ReturnType))
- throw new InvalidOperationException("Invalid type for field: " + field);
- result = fields[field].Value;
- }
- protected void SetMember_Allowed(SetMemberBinder binder, object value) {
- string field = binder.Name;
- if(!fields.ContainsKey(field)) {
- AddField(new DynamicField(field, value.GetType(), value));
- return;
- }
- Type declaringType = fields[field].Type;
- if (value.GetType() != declaringType && !value.GetType().IsSubclassOf(declaringType))
- throw new InvalidOperationException("Invalid type for field: " + field);
- fields[field].Value = value;
- }
- protected void SetMember_NotAllowed(SetMemberBinder binder, object value) {
- string field = binder.Name;
- if (!fields.ContainsKey(field))
- throw new InvalidOperationException("Invalid field: " + field);
- Type declaringType = fields[field].Type;
- if (value.GetType() != declaringType && !value.GetType().IsSubclassOf(declaringType))
- throw new InvalidOperationException("Invalid type for field: " + field);
- fields[field].Value = value;
- }
- }
- public class DynamicField {
- public string Name { get; private set; }
- public Type Type { get; private set; }
- public object Value { get; set; }
- public DynamicField(string name, Type type, object value = null) {
- Name = name;
- Type = type;
- Value = value;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement