我想从服务发送到服务对象:
public abstract class Notification : AggregateRoot
{
public string Title { get; set; }
public string Content { get; set; }
public DateTime Created { get; set; }
public NotificationType NotificationType { get; set; }
}
public class Alert : Notification
{
public object LinkedObject { get; set; }
public bool WasSeen { get; set; }
}
从我的单元测试:
[Theory, AutoNSubstituteData]
public async void Send_NotificationIsAlertTypeDocumentDontExist_DocumentShouldBeCreatedAndNotificationSaved(
IDocumentDbRepository<AlertsDocument> repository,
CampaignAlertsSender sender,
Alert notification
)
{
// Arrange
notification.NotificationType = NotificationType.Alert;
notification.LinkedObject = new
{
MerchantId = Guid.NewGuid()
};
repository.GetItemAsync(Arg.Any<Expression<Func<AlertsDocument, bool>>>()).Returns((Task<AlertsDocument>) null);
// Act
await sender.SendAsync(notification);
// Assert
await repository.Received(1).GetItemAsync(Arg.Any<Expression<Func<AlertsDocument, bool>>>());
await repository.Received(1).CreateItemAsync(Arg.Any<AlertsDocument>());
}
查看链接对象object
,但我使用new
。并将其发送给服务。
public override async Task SendAsync(Notification notification)
{
if(notification == null)
throw new ArgumentNullException(nameof(notification));
var alert = notification as Alert;
if(alert == null)
throw new ArgumentException();
var linkedObject = alert.LinkedObject as dynamic;
Guid merchantId = Guid.Parse(linkedObject.MerchantId); // here is problem! linkedObject "object" dont have "MerchantId".
var document = await Repository.GetItemAsync(doc => doc.MerchantId == merchantId);
if (document == null)
{
document = new AlertsDocument
{
MerchantId = merchantId,
Entity = new List<Alert>()
};
document.Entity.Add(alert);
}
}
这是问题! linkedObject&#34; object&#34;没有&#34; MerchantId&#34;。 但为什么?在debuging的同时,我在linkedObject中看到了MerchantId的值。 怎么做?
错误:
An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in mscorlib.dll but was not handled in user code
Additional information: 'object' does not contain a definition for 'MerchantId'
答案 0 :(得分:1)
LinkedObject
创建为匿名类型,生成为internal
类型。如果访问该对象的代码不在同一个程序集中,那么您将收到该错误。调试器可以看到,因为它正在使用反射,但是当您尝试通过dynamic
访问它时,您会收到错误(同样是因为匿名类型是作为内部生成的)。
然而,您仍然可以通过反思来实现它。
var linkedObject = alert.LinkedObject as dynamic;
Guid merchantId = (Guid)linkedObject.GetType()
.GetProperty("MerchantId")
.GetValue(linkedObject, null);
但这可能会非常快。
如果你看看我在这里提供的答案
How do you unit test ASP.NET Core MVC Controllers that return anonymous objects?
使用动态包装器,它使用引擎盖下的反射来访问匿名类型的属性。
同样的理论适用,您可以使用该包装器来访问linkedObject的属性。
var linkedObject = new DynamicObjectResultValue(alert.LinkedObject);
Guid merchantId = (Guid)linkedObject.MerchantId;
答案 1 :(得分:0)
从您的代码中看来,MerchantId
已经是Guid
,所以您只需要强制转换它,而不是解析:
var linkedObject = (dynamic)alert.LinkedObject;
var merchantId = (Guid)linkedObject.MerchantId;