鉴于它是密封的并且报告它没有公共构造函数,您将不得不提供一种创建实例的方法,并且它可能是基于反射的解决方案。只读属性也增加了 AutoFixture 的复杂性。
在没有看到构造函数的情况下,或者只读属性是否有任何支持字段的情况下,我将通过以下工作示例进行一些假设。
创建可以创建TokenCacheItem 并设置其属性的东西:
public class MutableTokenCacheItem
{
private TokenCacheItem _tokenCacheItem;
public string Authority { get => _tokenCacheItem.Authority; set => SetPropertyValue(x => x.Authority, value); }
public string ClientId { get => _tokenCacheItem.ClientId; set => SetPropertyValue(x => x.ClientId, value); }
public DateTimeOffset ExpiresOn { get => _tokenCacheItem.ExpiresOn; set => SetPropertyValue(x => x.ExpiresOn, value); }
public string FamilyName { get => _tokenCacheItem.FamilyName; set => SetPropertyValue(x => x.FamilyName, value); }
public string GivenName { get => _tokenCacheItem.GivenName; set => SetPropertyValue(x => x.GivenName, value); }
public string IdentityProvider { get => _tokenCacheItem.IdentityProvider; set => SetPropertyValue(x => x.IdentityProvider, value); }
public string TenantId { get => _tokenCacheItem.TenantId; set => SetPropertyValue(x => x.TenantId, value); }
public MutableTokenCacheItem()
{
var ctor = typeof(TokenCacheItem).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Single();
_tokenCacheItem = (TokenCacheItem)ctor.Invoke(null);
}
private void SetPropertyValue<P>(Expression<Func<TokenCacheItem, P>> expression, object value)
{
var body = expression.Body as MemberExpression;
var backingField = typeof(TokenCacheItem).GetRuntimeFields().Where(a => Regex.IsMatch(a.Name, $"\\A<{body.Member.Name}>k__BackingField\\Z")).Single();
backingField.SetValue(_tokenCacheItem, value);
}
public TokenCacheItem AsImmutableTokenCacheItem()
{
return _tokenCacheItem;
}
}
创建一个样本构建器以将其很好地固定到 AutoFixture 中:
public class TokenCacheItemSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (typeof(TokenCacheItem).Equals(t))
{
var mutableTokenCacheItem = context.Create<MutableTokenCacheItem>();
return mutableTokenCacheItem.AsImmutableTokenCacheItem();
}
return new NoSpecimen();
}
}
添加自定义并开始使用:
var fixture = new Fixture();
fixture.Customizations.Add(new TokenCacheItemSpecimenBuilder());
fixture.Create<TokenCacheItem>();
工作 LINQPad 示例:
void Main()
{
var fixture = new Fixture();
fixture.Customizations.Add(new TokenCacheItemSpecimenBuilder());
Console.Write(fixture.Create<TokenCacheItem>());
}
public class TokenCacheItemSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (typeof(TokenCacheItem).Equals(t))
{
var mutableTokenCacheItem = context.Create<MutableTokenCacheItem>();
return mutableTokenCacheItem.AsImmutableTokenCacheItem();
}
return new NoSpecimen();
}
}
public class MutableTokenCacheItem
{
private TokenCacheItem _tokenCacheItem;
public string Authority { get => _tokenCacheItem.Authority; set => SetPropertyValue(x => x.Authority, value); }
public string ClientId { get => _tokenCacheItem.ClientId; set => SetPropertyValue(x => x.ClientId, value); }
public DateTimeOffset ExpiresOn { get => _tokenCacheItem.ExpiresOn; set => SetPropertyValue(x => x.ExpiresOn, value); }
public string FamilyName { get => _tokenCacheItem.FamilyName; set => SetPropertyValue(x => x.FamilyName, value); }
public string GivenName { get => _tokenCacheItem.GivenName; set => SetPropertyValue(x => x.GivenName, value); }
public string IdentityProvider { get => _tokenCacheItem.IdentityProvider; set => SetPropertyValue(x => x.IdentityProvider, value); }
public string TenantId { get => _tokenCacheItem.TenantId; set => SetPropertyValue(x => x.TenantId, value); }
public MutableTokenCacheItem()
{
var ctor = typeof(TokenCacheItem).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Single();
_tokenCacheItem = (TokenCacheItem)ctor.Invoke(null);
}
private void SetPropertyValue<P>(Expression<Func<TokenCacheItem, P>> expression, object value)
{
var body = expression.Body as MemberExpression;
var backingField = typeof(TokenCacheItem).GetRuntimeFields().Where(a => Regex.IsMatch(a.Name, $"\\A<{body.Member.Name}>k__BackingField\\Z")).Single();
backingField.SetValue(_tokenCacheItem, value);
}
public TokenCacheItem AsImmutableTokenCacheItem()
{
return _tokenCacheItem;
}
}
public sealed class TokenCacheItem
{
public string Authority { get; }
public string ClientId { get; }
public DateTimeOffset ExpiresOn { get; }
public string FamilyName { get; }
public string GivenName { get; }
public string IdentityProvider { get; }
public string TenantId { get; }
private TokenCacheItem() { }
}
结果:
YMMV 取决于实际的 TokenCacheItem 实现,尽管它可能并不遥远。