예제 #1
0
        private static ITypeReadAccessor Create(Type type, object @object, AccessorMemberTypes types,
                                                AccessorMemberScope scope, out AccessorMembers members)
        {
            lock (Sync)
            {
                var key = KeyForType(type, types, scope);

                if (AccessorCache.TryGetValue(key, out var accessor))
                {
                    members = type.IsAnonymous()
                        ? CreateAnonymousReadAccessorMembers(type)
                        : CreateReadAccessorMembers(type, types, scope);
                    return(accessor);
                }

                var anonymous = type.IsAnonymous();

                accessor = anonymous
                    ? CreateAnonymousReadAccessor(type, out members, @object)
                    : CreateReadAccessor(type, out members, types, scope);

                AccessorCache[key] = accessor;
                return(accessor);
            }
        }
예제 #2
0
        private AccessorMembers(Type type, AccessorMemberTypes types, AccessorMemberScope scope)
        {
            DeclaringType = type;
            DisplayName   = GetDisplayName();
            Types         = types;
            Scope         = scope;

            NameToMember = new Dictionary <string, AccessorMember>(StringComparer.OrdinalIgnoreCase);

            var flags = BindingFlags.Instance | BindingFlags.Static;

            if (scope.HasFlagFast(AccessorMemberScope.Public))
            {
                flags |= BindingFlags.Public;
            }
            if (scope.HasFlagFast(AccessorMemberScope.Private))
            {
                flags |= BindingFlags.NonPublic;
            }

            // First pass: everything
            SetWith(type, types, scope, flags);

            // Second pass: declared only (prefer overrides)
            SetWith(type, types, scope, flags | BindingFlags.DeclaredOnly);

            var fields     = FieldInfo ?? Enumerable.Empty <FieldInfo>();
            var properties = PropertyInfo ?? Enumerable.Empty <PropertyInfo>();
            var methods    = MethodInfo ?? Enumerable.Empty <MethodInfo>();

            MemberInfo = fields.Cast <MemberInfo>().Concat(properties).Concat(methods).OrderBy(TryOrderMemberInfo).ToArray();
            Members    = NameToMember.Values.OrderBy(TryOrderMember).ToList();
        }
예제 #3
0
        private static AccessorMembersKey KeyForType(Type type, AccessorMemberTypes types, AccessorMemberScope scope)
        {
            var key = type.IsAnonymous()
                ? new AccessorMembersKey(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public)
                : new AccessorMembersKey(type, types, scope);

            return(key);
        }
예제 #4
0
 public static ITypeReadAccessor Create(object @object, AccessorMemberTypes types, AccessorMemberScope scope,
                                        out AccessorMembers members)
 {
     if (@object is Type type)
     {
         return(Create(type, types, scope, out members));
     }
     type = @object.GetType();
     return(Create(type, @object, types, scope, out members));
 }
예제 #5
0
 public static ITypeReadAccessor Create(object @object,
                                        AccessorMemberTypes types = AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                        AccessorMemberScope scope = AccessorMemberScope.All)
 {
     if (@object is Type type)
     {
         return(Create(type, types, scope));
     }
     type = @object.GetType();
     return(Create(type, @object, types, scope, out _));
 }
예제 #6
0
        private void SetWith(Type type, AccessorMemberTypes types, AccessorMemberScope scope, BindingFlags flags)
        {
            if (types.HasFlagFast(AccessorMemberTypes.Fields))
            {
                var fields = type.GetFields(flags).OrderBy(f => f.Name);
                FieldInfo = FieldInfo == null?fields.ToArray() : FieldInfo.Concat(fields).Distinct().ToArray();

                foreach (var field in FieldInfo)
                {
                    NameToMember[field.Name] =
                        new AccessorMember(type, field.Name, field.FieldType, true, true, false, scope,
                                           AccessorMemberType.Field, field);
                }
            }

            if (types.HasFlagFast(AccessorMemberTypes.Properties))
            {
                var properties = type.GetProperties(flags).OrderBy(p => p.Name);
                PropertyInfo = PropertyInfo == null
                    ? properties.ToArray()
                    : PropertyInfo.Concat(properties).Distinct().ToArray();

                foreach (var property in PropertyInfo)
                {
                    NameToMember[property.Name] =
                        new AccessorMember(type, property.Name, property.PropertyType, CanAccessorRead(property, scope),
                                           CanAccessorWrite(property, scope),
                                           false, scope, AccessorMemberType.Property, property);
                }
            }

            if (types.HasFlagFast(AccessorMemberTypes.Methods))
            {
                var methods = type.GetMethods(flags).OrderBy(m => m.Name);
                MethodInfo = MethodInfo == null?methods.ToArray() : MethodInfo.Concat(methods).Distinct().ToArray();

                foreach (var method in MethodInfo)
                {
                    NameToMember[method.Name] =
                        new AccessorMember(type, method.Name, method.ReturnType, false, false, true, scope,
                                           AccessorMemberType.Method,
                                           method);
                }
            }
        }
예제 #7
0
        private static ITypeWriteAccessor CreateImpl(Type type, AccessorMemberTypes types, AccessorMemberScope scope,
                                                     out AccessorMembers members)
        {
            lock (Sync)
            {
                var key = KeyForType(type, types, scope);

                if (AccessorCache.TryGetValue(key, out var accessor))
                {
                    members = CreateWriteAccessorMembers(type, types, scope);
                    return(accessor);
                }

                accessor           = CreateWriteAccessor(type, types, scope, out members);
                AccessorCache[key] = accessor;
                return(accessor);
            }
        }
예제 #8
0
 private static AccessorMembers CreateReadAccessorMembers(Type type,
                                                          AccessorMemberTypes types = AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                                          AccessorMemberScope scope = AccessorMemberScope.All)
 {
     return(AccessorMembers.Create(type, types, scope));
 }
예제 #9
0
 public AccessorMembersKey(Type type, AccessorMemberTypes types, AccessorMemberScope scope)
 {
     Type  = type;
     Scope = scope;
     Types = types;
 }
예제 #10
0
 private static AccessorMembers CreateWriteAccessorMembers(Type type, AccessorMemberTypes types,
                                                           AccessorMemberScope scope)
 {
     return(AccessorMembers.Create(type, types, scope));
 }
예제 #11
0
 public static ITypeReadAccessor Create(Type type,
                                        AccessorMemberTypes types = AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                        AccessorMemberScope scope = AccessorMemberScope.All)
 {
     return(Create(type, null, types, scope, out _));
 }
예제 #12
0
 public static ITypeReadAccessor Create(Type type, AccessorMemberTypes types, AccessorMemberScope scope,
                                        out AccessorMembers members)
 {
     return(Create(type, null, types, scope, out members));
 }
예제 #13
0
        private static ITypeWriteAccessor CreateWriteAccessor(Type type, AccessorMemberTypes types,
                                                              AccessorMemberScope scope, out AccessorMembers members)
        {
            members = CreateWriteAccessorMembers(type, types, scope);

            if (type.NeedsLateBoundAccessor(members))
            {
                return(new LateBoundTypeWriteAccessor(members));
            }

            var name = type.CreateNameForWriteAccessor(members.Types, members.Scope);

            var tb = DynamicAssembly.Module.DefineType(name,
                                                       TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit |
                                                       TypeAttributes.AutoClass | TypeAttributes.AnsiClass);

            tb.AddInterfaceImplementation(typeof(ITypeWriteAccessor));

            //
            // Generate proxies for all backing field setters we will need for this type
            //
            var setFieldDelegateMethods    = new Dictionary <MethodBuilder, Delegate>();
            var getFieldDelegateMethods    = new List <MethodBuilder>();
            var invokeFieldDelegateMethods = new List <MethodBuilder>();
            var callSwaps = new Dictionary <AccessorMember, MethodInfo>();

            foreach (var member in members)
            {
                if (!member.CanWrite)
                {
                    continue; // can't write / is a computed property
                }
                if (!(member.MemberInfo is PropertyInfo property))
                {
                    continue; // not a property
                }
                if (property.GetSetMethod(true) != null)
                {
                    continue; // has public setter
                }
                var backingField = member.BackingField;
                if (backingField == null)
                {
                    continue;
                }

                var setFieldMethod = new DynamicMethod($"set_{member.Name}", typeof(void),
                                                       new[] { backingField.DeclaringType, backingField.FieldType }, backingField.DeclaringType, true);

                var setFieldIl = setFieldMethod.GetILGeneratorInternal();
                setFieldIl.Ldarg_0();
                setFieldIl.Ldarg_1();
                setFieldIl.Stfld(backingField);
                setFieldIl.Ret();

                var setFieldDelegateType =
                    typeof(Action <,>).MakeGenericType(backingField.DeclaringType, backingField.FieldType);
                var setFieldDelegate = setFieldMethod.CreateDelegate(setFieldDelegateType);

                // At this point we have a valid delegate that will set the private backing field...

                var setFieldDelegateField = tb.DefineField(
                    $"_setFieldDelegate_{member.Type.Namespace}_{member.Type.Name}_{backingField.Name}",
                    setFieldDelegateType,
                    FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly);

                var setFieldDelegateMethod = tb.DefineMethod(
                    $"_set_setFieldDelegate_{member.Type.Namespace}_{member.Type.Name}_{backingField.Name}",
                    MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard,
                    typeof(void),
                    new[] { setFieldDelegateType });

                var setFieldDelegateIl = setFieldDelegateMethod.GetILGeneratorInternal();
                setFieldDelegateIl.Ldarg_0();
                setFieldDelegateIl.Stsfld(setFieldDelegateField);
                setFieldDelegateIl.Ret();

                setFieldDelegateMethods.Add(setFieldDelegateMethod, setFieldDelegate);

                // At this point we've defined a static field to store our delegate setter and a method to set that field...

                var getFieldDelegateMethod = tb.DefineMethod(
                    $"_get_setFieldDelegate_{member.Type.Namespace}_{member.Type.Name}_{backingField.Name}",
                    MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard,
                    setFieldDelegateType, null);

                var getFieldDelegateIl = getFieldDelegateMethod.GetILGeneratorInternal();
                getFieldDelegateIl.Ldsfld(setFieldDelegateField);
                getFieldDelegateIl.Ret();

                getFieldDelegateMethods.Add(getFieldDelegateMethod);

                // At this point we can get and set the static field delegates, and now we need to cache a method to invoke them...

                var invokeFieldDelegateMethod = tb.DefineMethod(
                    $"_invoke_setFieldDelegate_{member.Type.Namespace}_{member.Type.Name}_{backingField.Name}",
                    MethodAttributes.Static | MethodAttributes.Private, CallingConventions.Standard,
                    typeof(void),
                    new[] { backingField.DeclaringType, backingField.FieldType });

                var invokeFieldDelegateIl = invokeFieldDelegateMethod.GetILGenerator();
                invokeFieldDelegateIl.Emit(OpCodes.Ldsfld, setFieldDelegateField);
                invokeFieldDelegateIl.Emit(OpCodes.Ldarg_0);
                invokeFieldDelegateIl.Emit(OpCodes.Ldarg_1);
                invokeFieldDelegateIl.Emit(OpCodes.Callvirt, setFieldDelegateType.GetMethod("Invoke"));
                invokeFieldDelegateIl.Emit(OpCodes.Ret);

                invokeFieldDelegateMethods.Add(invokeFieldDelegateMethod);
                callSwaps.Add(member, invokeFieldDelegateMethod);
            }

            //
            // Type Type =>:
            //
            {
                var getType = tb.DefineMethod($"get_{nameof(ITypeWriteAccessor.Type)}",
                                              MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                              MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.SpecialName, typeof(Type),
                                              Type.EmptyTypes);
                var il = getType.GetILGeneratorInternal();
                il.Ldtoken(type);
                il.CallOrCallvirt(type,
                                  typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle), BindingFlags.Static | BindingFlags.Public));
                il.Ret();

                var getTypeProperty = tb.DefineProperty(nameof(ITypeWriteAccessor.Type), PropertyAttributes.None,
                                                        typeof(object), new[] { typeof(string) });
                getTypeProperty.SetGetMethod(getType);

                tb.DefineMethodOverride(getType,
                                        typeof(ITypeWriteAccessor).GetMethod($"get_{nameof(ITypeWriteAccessor.Type)}"));
            }

            //
            // bool TrySetValue(object target, string key, object value):
            //
            {
                var trySetValue = tb.DefineMethod(nameof(IWriteAccessor.TrySetValue),
                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                  MethodAttributes.Virtual | MethodAttributes.NewSlot, typeof(bool),
                                                  new[] { typeof(object), typeof(string), typeof(object) });
                var il = trySetValue.GetILGeneratorInternal();

                var branches = new Dictionary <AccessorMember, Label>();
                foreach (var member in members)
                {
                    if (!member.CanWrite)
                    {
                        continue;
                    }

                    branches.Add(member, il.DefineLabel());
                }

                foreach (var member in members)
                {
                    if (!member.CanWrite)
                    {
                        continue;
                    }

                    il.Ldarg_2();                                         // key
                    il.GotoIfStringEquals(member.Name, branches[member]); // if (key == "{member.Name}") goto found;
                }

                foreach (var member in members)
                {
                    if (!member.CanWrite)
                    {
                        continue;
                    }

                    il.MarkLabel(branches[member]); // found:

                    il.Ldarg_1();                   // target
                    il.CastOrUnbox(type);           // ({Type}) target
                    il.Ldarg_3();                   // value

                    switch (member.MemberInfo)      // target.{member.Name} = value
                    {
                    case PropertyInfo property:

                        il.CastOrUnboxAny(property.PropertyType);
                        il.CallOrCallvirt(type, GetOrSwapPropertySetter(property, callSwaps, member));
                        break;

                    case FieldInfo field:
                        il.CastOrUnboxAny(field.FieldType);
                        il.Stfld(field);
                        break;
                    }

                    il.Ldc_I4_1(); //     1
                    il.Ret();      //     return 1 (true)
                }

                il.Ldnull();   //     null
                il.Starg_S();  //     value = null
                il.Ldc_I4_0(); //     0
                il.Ret();      //     return 0 (false)

                tb.DefineMethodOverride(trySetValue,
                                        typeof(IWriteAccessor).GetMethod(nameof(IWriteAccessor.TrySetValue)));
            }

            //
            // object this[object target, string key] = object value:
            //
            {
                var setItem = tb.DefineMethod("set_Item",
                                              MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                              MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.SpecialName, typeof(void),
                                              new[] { typeof(object), typeof(string), typeof(object) });
                var il = setItem.GetILGeneratorInternal();

                var branches = new Dictionary <AccessorMember, Label>();
                foreach (var member in members)
                {
                    if (!member.CanWrite)
                    {
                        continue;
                    }

                    branches.Add(member, il.DefineLabel());
                }

                foreach (var member in members)
                {
                    if (!member.CanWrite)
                    {
                        continue;
                    }

                    il.Ldarg_2();                                         // key
                    il.GotoIfStringEquals(member.Name, branches[member]); // if (key == "{member.Name}") goto found;
                }

                foreach (var member in members)
                {
                    if (!member.CanWrite)
                    {
                        continue;
                    }

                    il.MarkLabel(branches[member]); // found:

                    il.Ldarg_1();                   // target
                    il.CastOrUnbox(type);           // ({Type}) target
                    il.Ldarg_3();                   // value

                    switch (member.MemberInfo)      // result = target.{member.Name}
                    {
                    case PropertyInfo property:
                        il.CastOrUnboxAny(property.PropertyType);
                        il.CallOrCallvirt(type, GetOrSwapPropertySetter(property, callSwaps, member));
                        break;

                    case FieldInfo field:
                        il.CastOrUnboxAny(field.FieldType);
                        il.Stfld(field);
                        break;
                    }

                    il.Ret(); // return result;
                }

                il.Newobj(typeof(ArgumentNullException).GetConstructor(Type.EmptyTypes)).Throw();

                var item = tb.DefineProperty("Item", PropertyAttributes.SpecialName, typeof(object),
                                             new[] { typeof(string) });
                item.SetSetMethod(setItem);

                tb.DefineMethodOverride(setItem, typeof(IWriteAccessor).GetMethod("set_Item"));
            }

            var typeInfo = tb.CreateTypeInfo();

            // Now we need to set the static delegate fields on this type...

            foreach (var entry in setFieldDelegateMethods)
            {
                var setFieldMethod = typeInfo.GetMethod(entry.Key.Name, BindingFlags.Static | BindingFlags.NonPublic);
                if (setFieldMethod == null)
                {
                    continue;
                }

                setFieldMethod.Invoke(null, new object[] { entry.Value });
            }

            // Test that we can access the static fields correctly...

            foreach (var entry in getFieldDelegateMethods)
            {
                var getFieldMethod = typeInfo.GetMethod(entry.Name, BindingFlags.Static | BindingFlags.NonPublic);
                if (getFieldMethod == null)
                {
                    continue;
                }

                var field = getFieldMethod.Invoke(null, null);
            }

            // Finally, test that we can invoke the delegate and set a backing field

            foreach (var entry in invokeFieldDelegateMethods)
            {
                if (entry.Name != "_invoke_setFieldDelegate_System_String_<Id>k__BackingField")
                {
                    continue;
                }

                var invokeFieldMethod = typeInfo.GetMethod(entry.Name, BindingFlags.Static | BindingFlags.NonPublic);
                if (invokeFieldMethod == null)
                {
                    throw new NullReferenceException();
                }

                var test = Activator.CreateInstance(type);
                invokeFieldMethod.Invoke(null, new[] { test, "Foo" });
            }

            return((ITypeWriteAccessor)Activator.CreateInstance(typeInfo.AsType(), false));
        }
예제 #14
0
 public static bool HasFlagFast(this AccessorMemberTypes value, AccessorMemberTypes flag)
 {
     return((value & flag) != 0);
 }
예제 #15
0
 public static ITypeReadAccessor Create(object @object, AccessorMemberTypes types, out AccessorMembers members)
 {
     return(Create(@object, types, AccessorMemberScope.All,
                   out members));
 }
예제 #16
0
        private static ITypeReadAccessor CreateReadAccessor(Type type, out AccessorMembers members,
                                                            AccessorMemberTypes types = AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                                            AccessorMemberScope scope = AccessorMemberScope.All)
        {
            members = CreateReadAccessorMembers(type, types, scope);

            if (type.NeedsLateBoundAccessor(members))
            {
                return(new LateBoundTypeReadAccessor(members));
            }

            var name = type.CreateNameForReadAccessor(members.Types, members.Scope);

            TypeBuilder tb;

            try
            {
                tb = DynamicAssembly.Module.DefineType(
                    name,
                    TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit |
                    TypeAttributes.AutoClass | TypeAttributes.AnsiClass);

                tb.AddInterfaceImplementation(typeof(ITypeReadAccessor));
            }
            catch (ArgumentException e)
            {
                if (e.Message == "Duplicate type name within an assembly.")
                {
                    throw new ArgumentException($"Duplicate type name within an assembly: {name}", nameof(name),
                                                e);
                }
                throw;
            }

            //
            // Type Type =>:
            //
            tb.MemberProperty(nameof(ITypeReadAccessor.Type), type,
                              typeof(ITypeReadAccessor).GetMethod($"get_{nameof(ITypeReadAccessor.Type)}"));

            //
            // bool TryGetValue(object target, string key, out object value):
            //
            {
                var tryGetValue = tb.DefineMethod(nameof(ITypeReadAccessor.TryGetValue),
                                                  MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                                  MethodAttributes.Virtual | MethodAttributes.NewSlot, typeof(bool),
                                                  new[] { typeof(object), typeof(string), typeof(object).MakeByRefType() });

                var il = tryGetValue.GetILGeneratorInternal();

                var branches = new Dictionary <AccessorMember, Label>();
                foreach (var member in members)
                {
                    branches.Add(member, il.DefineLabel());
                }
                var fail = il.DefineLabel();

                foreach (var member in members)
                {
                    il.Ldarg_2();                                         // key
                    il.GotoIfStringEquals(member.Name, branches[member]); // if (key == "Foo") goto found;
                }

                il.Br(fail);

                foreach (var member in members)
                {
                    il.MarkLabel(branches[member]); // found:
                    il.Ldarg_3();                   // value
                    il.Ldarg_1();                   // target
                    il.CastOrUnbox(type);           // ({Type}) target
                    switch (member.MemberInfo)      // result = target.{member.Name}
                    {
                    case PropertyInfo property:
                        var getMethod = property.GetGetMethod(true);
                        il.Callvirt(getMethod);
                        break;

                    case FieldInfo field:
                        il.Ldfld(field);
                        break;
                    }

                    il.MaybeBox(member.Type); // (object) result
                    il.Stind_Ref();           // value = result
                    il.Ldc_I4_1();            // 1
                    il.Ret();                 // return 1 (true)
                }

                il.MarkLabel(fail);
                il.Ldarg_3();   // value
                il.Ldnull();    // null
                il.Stind_Ref(); // value = null
                il.Ldc_I4_0();  // 0
                il.Ret();       // return 0 (false)

                tb.DefineMethodOverride(tryGetValue,
                                        typeof(IReadAccessor).GetMethod(nameof(IReadAccessor.TryGetValue)));
            }

            //
            // object this[object target, string key]:
            //
            {
                var getItem = tb.DefineMethod("get_Item",
                                              MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                              MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.SpecialName, typeof(object),
                                              new[] { typeof(object), typeof(string) });

                var il = getItem.GetILGeneratorInternal();

                var branches = new Dictionary <AccessorMember, Label>();
                foreach (var member in members)
                {
                    branches.Add(member, il.DefineLabel());
                }

                foreach (var member in members)
                {
                    il.Ldarg_2();                                         // key
                    il.GotoIfStringEquals(member.Name, branches[member]); // if (key == "{member.Name}") goto found;
                }

                foreach (var member in members)
                {
                    il.MarkLabel(branches[member]);
                    il.Ldarg_1();              // target
                    il.CastOrUnbox(type);      // ({Type}) target

                    switch (member.MemberInfo) // result = target.Foo
                    {
                    case PropertyInfo property:
                        var getMethod = property.GetGetMethod(true);
                        il.Callvirt(getMethod);
                        break;

                    case FieldInfo field:
                        il.Ldfld(field);
                        break;
                    }

                    il.MaybeBox(member.Type); // (object) result
                    il.Ret();                 // return result;
                }

                il.Newobj(typeof(ArgumentNullException).GetConstructor(Type.EmptyTypes));
                il.Throw();

                var getItemProperty = tb.DefineProperty("Item", PropertyAttributes.SpecialName, typeof(object),
                                                        new[] { typeof(string) });
                getItemProperty.SetGetMethod(getItem);

                tb.DefineMethodOverride(getItem, typeof(IReadAccessor).GetMethod("get_Item"));
            }

            var typeInfo = tb.CreateTypeInfo();

            return((ITypeReadAccessor)Activator.CreateInstance(typeInfo.AsType(), false));
        }
예제 #17
0
 public static ITypeWriteAccessor Create(Type type, AccessorMemberTypes types, AccessorMemberScope scope,
                                         out AccessorMembers members)
 {
     return(CreateImpl(type, types, scope, out members));
 }
예제 #18
0
 public static ITypeWriteAccessor Create(Type type,
                                         AccessorMemberTypes types = AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                         AccessorMemberScope scope = AccessorMemberScope.All)
 {
     return(CreateImpl(type, types, scope, out _));
 }
예제 #19
0
 public static string CreateNameForWriteAccessor(this Type type, AccessorMemberTypes types,
                                                 AccessorMemberScope scope)
 {
     return($"Write_{type.Name}_{types}_{scope}_{TypeHash(type, nameof(CreateNameForWriteAccessor))}");
 }
예제 #20
0
        private static AccessorMembersKey KeyForType(Type type, AccessorMemberTypes types, AccessorMemberScope scope)
        {
            var key = new AccessorMembersKey(type, types, scope);

            return(key);
        }