2016-07-15 8 views
0

は私がサービスオブジェクトにサービスから送信したいセーブ:Accesingと動的オブジェクト

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; } 
} 

そして、私のユニットテストから:私はnewでそれを作る

linkedobjectで
[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ですが、 。それをサービスに送る。

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' 

答えて

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のプロパティにアクセスできます。

​​
0

あなただけではなく、構文解析のために、それをキャストする必要があるのでMerchantIdは、すでにGuidようです:

var linkedObject = (dynamic)alert.LinkedObject; 
var merchantId = (Guid)linkedObject.MerchantId; 
+0

まだ同じ問題です。 – Nerf

関連する問題