Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
JLChnToZ committed May 30, 2023
1 parent 294d65c commit c2ebea3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 13 deletions.
63 changes: 51 additions & 12 deletions JLChnToZ.CommonUtils.Dynamic/Limitless.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,10 @@ public static dynamic Static(Type type) {
/// <param name="type">Optional base/interface type to wrap.</param>
/// <returns>The dynamic object with access to all members of it.</returns>
public static dynamic Wrap(object obj, Type type = null) {
if (obj == null) return null;
if (obj is Limitless ? type == null : obj is DynamicObject) return obj;
if (obj == null || (obj is Limitless && type == null) || obj is LimitlessInvokable) return obj;
if (type == null) return InternalWrap(obj);
obj = InternalUnwrap(obj);
var objType = obj.GetType();
if (!type.IsAssignableFrom(objType) && !objType.IsAssignableFrom(type))
if (!type.IsAssignableFrom(obj.GetType()))
throw new ArgumentException("Type mismatch", nameof(type));
return new Limitless(obj, type);
}
Expand Down Expand Up @@ -109,37 +107,76 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) {
result = Static(subType);
return true;
}
return typeInfo.TryGetValue(target, new[] { binder.Name }, out result);
if (typeInfo.TryGetValue(target, new[] { binder.Name }, out result))
return true;
if (target is DynamicObject dynamicObject && dynamicObject.TryGetMember(binder, out result))
return true;
return false;
}

public override bool TrySetMember(SetMemberBinder binder, object value) =>
typeInfo.TrySetValue(target, binder.Name, value) ||
typeInfo.TrySetValue(target, new[] { binder.Name }, value);
typeInfo.TrySetValue(target, new[] { binder.Name }, value) ||
(target is DynamicObject dynamicObject && dynamicObject.TrySetMember(binder, value));

public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) =>
typeInfo.TryGetValue(target, indexes, out result);
typeInfo.TryGetValue(target, indexes, out result) ||
(target is DynamicObject dynamicObject && dynamicObject.TryGetIndex(binder, indexes, out result));

public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) =>
typeInfo.TrySetValue(target, indexes, value);
typeInfo.TrySetValue(target, indexes, value) ||
(target is DynamicObject dynamicObject && dynamicObject.TrySetIndex(binder, indexes, value));

public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes) {
if (indexes.Length == 1) {
if (type.IsArray) return false;
if (type.IsAssignableFrom(typeof(IDictionary))) {
((IDictionary)target).Remove(indexes[0]);
return true;
}
if (type.IsAssignableFrom(typeof(IList)) && indexes[0] != null && indexes[0].GetType() == typeof(int)) {
((IList)target).RemoveAt(Convert.ToInt32(indexes[0]));
return true;
}
}
if (target is DynamicObject dynamicObject)
return dynamicObject.TryDeleteIndex(binder, indexes);
return false;
}

public override bool TryDeleteMember(DeleteMemberBinder binder) {
if (type.IsAssignableFrom(typeof(IDictionary))) {
((IDictionary)target).Remove(binder.Name);
return true;
}
if (target is DynamicObject dynamicObject)
return dynamicObject.TryDeleteMember(binder);
return false;
}

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) =>
typeInfo.TryInvoke(target, binder.Name, args, out result);
typeInfo.TryInvoke(target, binder.Name, args, out result) ||
(target is DynamicObject dynamicObject && dynamicObject.TryInvokeMember(binder, args, out result));

public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) {
if (target is Delegate del) {
result = InternalWrap(del.DynamicInvoke(InternalUnwrap(args)));
InternalWrap(args, args);
return true;
}
if (target is DynamicObject dynamicObject && dynamicObject.TryInvoke(binder, args, out result))
return true;
result = null;
return false;
}

public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result) =>
typeInfo.TryInvoke(target, $"op_{binder.Operation}", new[] { arg }, out result);
typeInfo.TryInvoke(target, $"op_{binder.Operation}", new[] { arg }, out result) ||
(target is DynamicObject dynamicObject && dynamicObject.TryBinaryOperation(binder, arg, out result));

public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result) =>
typeInfo.TryInvoke(target, $"op_{binder.Operation}", null, out result);
typeInfo.TryInvoke(target, $"op_{binder.Operation}", null, out result) ||
(target is DynamicObject dynamicObject && dynamicObject.TryUnaryOperation(binder, out result));

public override bool TryConvert(ConvertBinder binder, out object result) {
if (typeInfo.TryCast(target, binder.Type, out result))
Expand All @@ -149,7 +186,9 @@ public override bool TryConvert(ConvertBinder binder, out object result) {
result = convertible.ToType(binder.Type, null);
return true;
}
} catch (Exception) { }
} catch { }
if (target is DynamicObject dynamicObject && dynamicObject.TryConvert(binder, out result))
return true;
result = null;
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion JLChnToZ.CommonUtils.Dynamic/Utilites.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static MethodMatchLevel UnwrapParamAndCheck(Type type, ref object input)
}

public static object InternalWrap(object obj) =>
obj == null || obj is DynamicObject || Type.GetTypeCode(obj.GetType()) != TypeCode.Object ? obj : new Limitless(obj);
obj == null || obj is Limitless || obj is LimitlessInvokable || Type.GetTypeCode(obj.GetType()) != TypeCode.Object ? obj : new Limitless(obj);

public static void InternalWrap(object[] sourceObj, object[] destObj) {
if (sourceObj == null || destObj == null) return;
Expand Down

0 comments on commit c2ebea3

Please sign in to comment.