Der folgende Code funktioniert gut, solange ich eine Klasse ClassSameAssembly
in derselben Assembly wie die Klasse habe Program
. Wenn ich die Klasse ClassSameAssembly
in eine separate Assembly verschiebe, wird ein RuntimeBinderException
(siehe unten) ausgelöst. Ist es möglich, es zu lösen?
using System;
namespace ConsoleApplication2
{
public static class ClassSameAssembly
{
public static dynamic GetValues()
{
return new
{
Name = "Michael", Age = 20
};
}
}
internal class Program
{
private static void Main(string[] args)
{
var d = ClassSameAssembly.GetValues();
Console.WriteLine("{0} is {1} years old", d.Name, d.Age);
}
}
}
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
: 'Objekt' enthält keine Definition für 'Name'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at ConsoleApplication2.Program.Main(String[] args) in C:\temp\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
dynamic
c#-4.0
anonymous-types
mehanik
quelle
quelle
Antworten:
Ich glaube, das Problem ist, dass der anonyme Typ als generiert wird
internal
, so dass der Ordner nicht wirklich darüber Bescheid weiß.Versuchen Sie stattdessen, ExpandoObject zu verwenden:
Ich weiß, dass das etwas hässlich ist, aber es ist das Beste, was ich mir im Moment vorstellen kann ... Ich glaube nicht, dass Sie damit sogar einen Objektinitialisierer verwenden können, da
ExpandoObject
der Compiler zwar stark typisiert ist, aber nicht weiß, was er tun soll mit "Name" und "Alter". Sie können der Lage sein , dies zu tun:aber das ist nicht viel besser ...
Sie könnten möglicherweise eine Erweiterungsmethode schreiben, um einen anonymen Typ durch Reflektion in ein Expoo mit demselben Inhalt umzuwandeln. Dann könnten Sie schreiben:
Das ist allerdings ziemlich schrecklich :(
quelle
return Build<ExpandoObject>.NewObject(Name:"Micheal", Age: 20);
object
oder für einen generischen Typ tun (Sie können verlangen, dass es sich um eine Klasse handelt ...) und den Typ zur Ausführungszeit überprüfen.Sie können verwenden
[assembly: InternalsVisibleTo("YourAssemblyName")]
, um Ihre Baugruppeneinbauten sichtbar zu machen.quelle
Ich bin auf ein ähnliches Problem gestoßen und möchte Jon Skeets Antwort hinzufügen, dass es eine andere Option gibt. Der Grund, warum ich herausfand, war, dass ich feststellte, dass viele Erweiterungsmethoden in Asp MVC3 anonyme Klassen als Eingabe verwenden, um HTML-Attribute bereitzustellen (new {alt = "Image alt", style = "padding-top: 5px"} =>
Wie auch immer - diese Funktionen verwenden den Konstruktor der RouteValueDictionary-Klasse. Ich habe das selbst versucht und sicher funktioniert es - obwohl nur die erste Ebene (ich habe eine mehrstufige Struktur verwendet). SO - im Code wäre dies:
SO ... Was ist hier wirklich los? Ein Blick in das RouteValueDictionary zeigt diesen Code (Werte ~ = o oben):
SO - mit TypeDescriptor.GetProperties (o) könnten wir die Eigenschaften und Werte abrufen, obwohl der anonyme Typ in einer separaten Assembly als intern konstruiert wird! Und natürlich wäre dies ziemlich einfach zu erweitern, um es rekursiv zu machen. Und um eine Erweiterungsmethode zu erstellen, wenn Sie möchten.
Hoffe das hilft!
/Sieger
quelle
Hier ist eine rudimentäre Version einer Erweiterungsmethode für ToExpandoObject, die sicher Platz zum Polieren bietet.
quelle
Eine sauberere Lösung wäre:
Welches ist jetzt ein ExpandoObject.
Denken Sie daran, zu verweisen:
quelle
ToExpando-Erweiterungsmethode (in Jons Antwort erwähnt) für die Mutigen
quelle
Die folgende Lösung hat für mich in meinen Konsolenanwendungsprojekten funktioniert
Fügen Sie diese [Assembly: InternalsVisibleTo ("YourAssemblyName")] in \ Properties \ AssemblyInfo.cs des separaten Projekts ein, wobei die Funktion ein dynamisches Objekt zurückgibt.
"YourAssemblyName" ist der Assemblyname des aufrufenden Projekts. Sie können dies über Assembly.GetExecutingAssembly (). FullName erhalten, indem Sie es im aufrufenden Projekt ausführen.
quelle
Wenn Sie Newtonsoft.Json bereits in Ihrem Projekt verwenden (oder bereit sind, es zu diesem Zweck hinzuzufügen), können Sie diese schreckliche Erweiterungsmethode implementieren, auf die sich Jon Skeet in seiner Antwort wie folgt bezieht :
quelle