访问和保存动态对象
本文关键字:对象 动态 保存 访问 | 更新日期: 2023-09-27 17:57:02
我想从服务发送到服务对象:
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 "object" 没有 "MerchantId"。但是为什么?调试时,我在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'
LinkedObject
被创建为匿名类型,该匿名类型生成为internal
类型。如果访问对象的代码不在同一程序集中,则会收到该错误。调试器可以看到,因为它正在使用反射,但是当您尝试通过反射访问它时dynamic
会出现错误(再次因为匿名类型是作为内部生成的)。
但是,您仍然可以通过反射来获得它。
var linkedObject = alert.LinkedObject as dynamic;
Guid merchantId = (Guid)linkedObject.GetType()
.GetProperty("MerchantId")
.GetValue(linkedObject, null);
但这很快就会变得混乱。
如果你看看我在这里提供的答案
如何对返回匿名对象的核心 MVC 控制器 ASP.NET 进行单元测试?
使用了动态包装器,该包装器在后台使用反射来访问匿名类型的属性。
同样的理论也适用,你可以使用该包装器来访问linkedObject的属性。
var linkedObject = new DynamicObjectResultValue(alert.LinkedObject);
Guid merchantId = (Guid)linkedObject.MerchantId;
从您的代码来看,MerchantId
已经是一个 Guid
,所以你只需要强制转换它,而不是解析:
var linkedObject = (dynamic)alert.LinkedObject;
var merchantId = (Guid)linkedObject.MerchantId;