Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
JLChnToZ committed Jun 5, 2023
1 parent 2a3e315 commit 632ccf7
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 48 deletions.
87 changes: 48 additions & 39 deletions JLChnToZ.CommonUtils.Dynamic/Limitless.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections;
using System.Linq.Expressions;
using System.Dynamic;

namespace JLChnToZ.CommonUtils.Dynamic {
Expand Down Expand Up @@ -167,7 +166,7 @@ public override bool TryDeleteMember(DeleteMemberBinder binder) {
}

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

public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) {
Expand All @@ -182,12 +181,15 @@ public override bool TryInvoke(InvokeBinder binder, object[] args, out object re
return false;
}

internal bool TryInvoke(bool isStatic, string name, out object result, params object[] args) =>
typeInfo.TryInvoke(isStatic ? null : target, name, args, out result);

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

public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result) =>
typeInfo.TryInvoke(null, binder.Operation.ToOperatorMethodName(), new[] { target }, out result) ||
TryInvoke(true, binder.Operation.ToOperatorMethodName(), out result, target) ||
(target is DynamicObject dynamicObject && dynamicObject.TryUnaryOperation(binder, out result));

public override bool TryConvert(ConvertBinder binder, out object result) {
Expand All @@ -207,7 +209,7 @@ public override bool TryConvert(ConvertBinder binder, out object result) {

// Supports await ... syntax
public virtual LimitlessAwaiter GetAwaiter() =>
new LimitlessAwaiter(typeInfo.TryInvoke(target, nameof(GetAwaiter), null, out var awaiter) ? InternalUnwrap(awaiter) : target);
new LimitlessAwaiter(TryInvoke(false, nameof(GetAwaiter), out var awaiter, emptyArgs) ? InternalUnwrap(awaiter) : target);

// Supports foreach (... in ...) { ... } syntax
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
Expand All @@ -224,68 +226,75 @@ protected virtual IEnumerator GetEnumerator() {
public override int GetHashCode() => target?.GetHashCode() ?? 0;

public override bool Equals(object obj) {
if (ReferenceEquals(this, obj)) return true;
if (obj is Limitless wrapped) obj = wrapped.target;
if (ReferenceEquals(target, obj)) return true;
if (obj == null) return target == null;
return target.Equals(obj);
}

public static bool operator ==(Limitless a, Limitless b) {
if (ReferenceEquals(a.target, b.target)) return true;
if (ReferenceEquals(a, b)) return true;
object result;
if (a.typeInfo.TryInvoke(null, "op_Equality", new[] { a.target, b.target }, out result) ||
b.typeInfo.TryInvoke(null, "op_Equality", new[] { a.target, b.target }, out result))
if (a.TryInvoke(true, "op_Equality", out result, a.target, b.target) ||
b.TryInvoke(true, "op_Equality", out result, a.target, b.target))
return (bool)result;
return false;
return ReferenceEquals(a.target, b.target);
}

public static bool operator !=(Limitless a, Limitless b) {
if (ReferenceEquals(a.target, b.target)) return false;
if (ReferenceEquals(a, b)) return false;
object result;
if (a.typeInfo.TryInvoke(null, "op_Inequality", new[] { a.target, b.target }, out result) ||
b.typeInfo.TryInvoke(null, "op_Inequality", new[] { a.target, b.target }, out result))
if (a.TryInvoke(true, "op_Inequality", out result, a.target, b.target) ||
b.TryInvoke(true, "op_Inequality", out result, a.target, b.target))
return (bool)result;
return true;
return !ReferenceEquals(a.target, b.target);
}

public static bool operator ==(Limitless a, object b) {
if (b is Limitless wrapped) b = wrapped.target;
if (ReferenceEquals(a.target, b)) return true;
if (b is Limitless wrapped) {
if (ReferenceEquals(a, wrapped)) return true;
b = wrapped.target;
}
object result;
if (a.typeInfo.TryInvoke(null, "op_Equality", new[] { a.target, b }, out result)) return (bool)result;
if (b == null) return a.target == null;
if (TypeInfo.Get(b.GetType()).TryInvoke(null, "op_Equality", new[] { a.target, b }, out result)) return (bool)result;
return false;
if (a.TryInvoke(true, "op_Equality", out result, a.target, b) ||
b.TryInvoke(true, "op_Equality", out result, a.target, b))
return (bool)result;
return ReferenceEquals(a.target, b);
}

public static bool operator !=(Limitless a, object b) {
if (b is Limitless wrapped) b = wrapped.target;
if (ReferenceEquals(a.target, b)) return false;
if (b is Limitless wrapped) {
if (ReferenceEquals(a, wrapped)) return false;
b = wrapped.target;
}
object result;
if (a.typeInfo.TryInvoke(null, "op_Inequality", new[] { a.target, b }, out result)) return (bool)result;
if (b == null) return a.target != null;
if (TypeInfo.Get(b.GetType()).TryInvoke(null, "op_Inequality", new[] { a.target, b }, out result)) return (bool)result;
return true;
if (a.TryInvoke(true, "op_Inequality", out result, a.target, b) ||
b.TryInvoke(true, "op_Inequality", out result, a.target, b))
return (bool)result;
return !ReferenceEquals(a.target, b);
}

public static bool operator ==(object a, Limitless b) {
if (a is Limitless wrapped) a = wrapped.target;
if (ReferenceEquals(a, b.target)) return true;
if (a is Limitless wrapped) {
if (ReferenceEquals(wrapped, b)) return true;
a = wrapped.target;
}
object result;
if (b.typeInfo.TryInvoke(null, "op_Equality", new[] { a, b.target }, out result)) return (bool)result;
if (a == null) return b.target == null;
if (TypeInfo.Get(a.GetType()).TryInvoke(null, "op_Equality", new[] { a, b.target }, out result)) return (bool)result;
return false;
if (a.TryInvoke(true, "op_Equality", out result, a, b.target) ||
b.TryInvoke(true, "op_Equality", out result, a, b.target))
return (bool)result;
return ReferenceEquals(a, b.target);
}

public static bool operator !=(object a, Limitless b) {
if (a is Limitless wrapped) a = wrapped.target;
if (ReferenceEquals(a, b.target)) return false;
if (a is Limitless wrapped) {
if (ReferenceEquals(wrapped, b)) return false;
a = wrapped.target;
}
object result;
if (b.typeInfo.TryInvoke(null, "op_Inequality", new[] { a, b.target }, out result)) return (bool)result;
if (a == null) return b.target != null;
if (TypeInfo.Get(a.GetType()).TryInvoke(null, "op_Inequality", new[] { a, b.target }, out result)) return (bool)result;
return true;
if (a.TryInvoke(true, "op_Inequality", out result, a, b.target) ||
b.TryInvoke(true, "op_Inequality", out result, a, b.target))
return (bool)result;
return !ReferenceEquals(a, b.target);
}
}
}
2 changes: 1 addition & 1 deletion JLChnToZ.CommonUtils.Dynamic/LimitlessInvokable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ internal protected bool TryCreateDelegate(Type delegateType, out Delegate result
) as MethodInfo;
if (matched != null && matched.ReturnType == invokeMethod.ReturnType) {
var target = InvokeTarget;
result = target == null ?
result = matched.IsStatic ?
Delegate.CreateDelegate(delegateType, matched, false) :
Delegate.CreateDelegate(delegateType, target, matched, false);
return result != null;
Expand Down
2 changes: 1 addition & 1 deletion JLChnToZ.CommonUtils.Dynamic/TypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ internal bool TryInvoke(object instance, string methodName, object[] args, out o
var safeArgs = args;
if (methods.TryGetValue(methodName, out var methodArrays) &&
TryGetMatchingMethod(methodArrays, ref safeArgs, out var resultMethod)) {
result = InternalWrap(resultMethod.Invoke(InternalUnwrap(instance), safeArgs));
result = InternalWrap(resultMethod.Invoke(resultMethod.IsStatic ? null : InternalUnwrap(instance), safeArgs));
InternalWrap(safeArgs, args);
return true;
}
Expand Down
18 changes: 11 additions & 7 deletions JLChnToZ.CommonUtils.Dynamic/Utilites.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ public static string ToOperatorMethodName(this ExpressionType expressionType) {
}
}

public static bool TryInvoke(this object obj, bool isStatic, string methodName, out object result, params object[] args) {
if (obj == null) {
result = null;
return false;
}
if (obj is Limitless limitObj)
return limitObj.TryInvoke(isStatic, methodName, out result, args);
return TypeInfo.Get(obj.GetType()).TryInvoke(isStatic ? null : obj, methodName, args, out result);
}

public static MethodInfo GetUndelyRaiseMethod(this EventInfo eventInfo, out Delegate backingDelegate, object instance = null) {
var raiseMethod = eventInfo.GetRaiseMethod(true);
backingDelegate = null;
Expand Down Expand Up @@ -134,17 +144,11 @@ public static Delegate ConvertAndFlatten(this Delegate del, Type toType = null)
continue;
}
if (current.GetType() != toType)
current = target == null ? Delegate.CreateDelegate(toType, method, false) :
current = method.IsStatic ? Delegate.CreateDelegate(toType, method, false) :
Delegate.CreateDelegate(toType, target, method, false);
del = Delegate.Combine(del, current);
}
return del;
}
}

internal enum MethodMatchLevel {
NotMatch,
Implicit,
Exact,
}
}

0 comments on commit 632ccf7

Please sign in to comment.