0

我有私有只读字段的课程

        public class Bar
        {
            private readonly ICollection<Foo> somePrivateCollection = new HashSet<Foo>();
            public IEnumerable<Foo> SomePublicCollection => somePrivateCollection;

            public int z;
        }

        public class Foo
        {
            public int x;
        }

我可以通过 GetField => SetValue 设置这个字段

        [Fact]
        public void someTest()
        {
            var fooObjects = new Faker<Foo>().Generate(1);
            var barObject = new Faker<Bar>().RuleFor(t => t.z, f => f.Random.Int())
                                            .Generate();

            barObject.GetType()
                     .GetField("somePrivateCollection", System.Reflection.BindingFlags.NonPublic |
                                                                        System.Reflection.BindingFlags.Instance)
                     .SetValue(barObject, fooObjects);
        }

但是如何使用相同的样式设置此字段

            var barObject = new Faker<Bar>().RuleFor(t => t.z, f => f.Random.Int())
                                            .RuleSetter("somePrivateCollection",fooObjects)
                                            .Generate();
4

1 回答 1

0

如果公共字段和私有字段之间的差异仅在 1 个字母中

 public class PrivateBinder : Binder
    {
        public override Dictionary<string, MemberInfo> GetMembers(Type t)
        {
            var members = base.GetMembers(t);

            var privateBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
            var allPrivateMembers = t.GetMembers(privateBindingFlags)
                                     .OfType<FieldInfo>()
                                     .Where( fi => fi.IsPrivate )
                                     .Where( fi => !fi.GetCustomAttributes(typeof(CompilerGeneratedAttribute)).Any() )
                                     .ToArray();

            foreach( var privateField in allPrivateMembers ){
                members.Add(privateField.Name, privateField);
            }
            return members;
        }
    }

public class DataFaker<T> : Faker<T> where T : class
    {
        public DataFaker(IBinder backingFieldBinder): base(binder: backingFieldBinder)
        {
        }

        public DataFaker<T> UsingPrivate()
        {
            return base.CustomInstantiator(f => Activator.CreateInstance(typeof(T), nonPublic: true) as T)
                    as DataFaker<T>;
        }

        public virtual Faker<T> RuleForPrivate<TProperty>(Expression<Func<T, TProperty>> property, TProperty value)
        {
            var propName = PropertyName.For(property);
            propName = propName.First()
                               .ToString()
                               .ToLower() +
                    propName.Substring(1);
            return AddRule(propName, (f, t) => value);
        }
    }

 var data =new DataFaker<Bar>(backingFieldBinder).UsingPrivate().RuleForPrivate(x => x.SomeCollection, value)
于 2021-03-18T02:11:25.433 回答