Frage

Lassen Sie uns sagen, ich habe eine Schnittstelle wie:

interface IThing {
   int Id { get; set; }
   string Title { get; set; }
}

Und in ASP.NET MVC Ich habe eine Form, die Beiträge zu einer Controller-Aktion wie folgt:

 [AcceptVerbs(HttpVerbs.Post)]
 public ActionResult NewThing([Bind(Exclude = "Id")] SimpleThing thing) {

    // code to validate and persist the thing can go here            
 }

Wo SimpleThing ist eine konkrete Klasse, die gerade noch Arbeitsgeräte IThing .

Aber ich möchte alle meine Methoden mit der Schnittstelle zu beschäftigen. Ich habe eine Datenanordnung, die NHiberate und seine eigenen verwendet IThing Implementierung (nennen wir es RealThing ). Ich kann nicht die SimpleThing es passieren, weil es um eine „unbekannte Wesen“ beschweren.

Hat jemand irgendwelche Ideen über einen sauberere Weg, dies zu tun? Ich dachte an etwas entlang der Linien eine Factory-Klasse zu verwenden. Aber wie würde ich die MVC-Form Bindemittel erhalten, es zu benutzen?

Danke!

War es hilfreich?

Lösung 3

Es gab einige gute Vorschläge hier und ich kam tatsächlich eine Lösung, die funktioniert. Allerdings endete ich zusammen mit etwas nach oben. Ich habe gerade Modelle erstellt, die für die Formulardaten I aufhängte und verwendet, um das Standardmodell Bindemittel.

Viel einfacher und es erlaubt mir, Daten zu erfassen, die nicht Teil meines Domain-Modells ist (dh. Wie ein Feld „Bemerkungen“).

Andere Tipps

Sie können mit benutzerdefinierten Modell Bindemittel . Allerdings Artikel über Msdn ist völlig nutzlos. Also besser zu suchen beschäftigen und etwas Besseres finden. Es gibt planaty von Artikeln zur Verfügung.

Ich kam mit zwei Ansätze dazu angestiftet.

Die erste war Code zu meiner NHibernate Repository-Klasse hinzufügen, um den einfachen POCO-Typen von dem MVC-Controller verwendet zu übersetzen ( SimpleThing ) auf die Art der Einheit, die NHibernate wollte ( RealThing ):

/// <summary>
/// A NHibernate generic repository.  Provides base of common 
/// methods to retrieve and update data.
/// </summary>
/// <typeparam name="T">The base type to expose 
/// repository methods for.</typeparam>
/// <typeparam name="K">The concrete type used by NHibernate</typeparam>
public class NHRepositoryBase<T, K> 
    : IRepository<T>
    where T : class
    where K : T, new()
{
    // repository methods ...

    /// <summary>
    /// Return T item as a type of K, converting it if necessary
    /// </summary>        
    protected static K GetKnownEntity(T item) {
        if (typeof(T) != typeof(K)) {
            K knownEntity = new K();

            foreach (var prop in typeof(T).GetProperties()) { 
                object value = prop.GetValue(item, null);
                prop.SetValue(knownEntity, value, null);
            }

            return knownEntity;
        } else {

            return (K)item;
        }            
    }

So kann jedes Verfahren im Repository rufen GetKnownEntity (T Artikel), und es wird Ihnen die Eigenschaften des Elements übergeben in der Art kopieren, die NHibernate will. Offensichtlich fühlte sich dies ein wenig klobig, so sah ich in benutzerdefinierte Modell Bindemittel.


Im zweiten Ansatz, habe ich ein eigenes Model Bindemittel wie folgt aus:

public class FactoryModelBinder<T> 
    : DefaultModelBinder 
    where T : new() 
{

    protected override object CreateModel(ControllerContext controllerContext, 
                                          ModelBindingContext bindingContext, 
                                          Type modelType) {

        return new T();                       
    }

}

Dann habe ich registriert, dass in Global.asax.cs mit:

ModelBinders.Binders.Add(typeof(IThing), 
            new FactoryModelBinder<RealThing>());

Und es funktioniert gut mit einer Controller Aktion, die wie folgt aussieht:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] IThing thing) {
    // code to process the thing goes here
}

Ich mag den zweiten Ansatz, aber die meisten meiner Dependency Injection-Zeug ist in der Controller-Klasse. Ich mag es nicht zu haben, alle diese Zuordnungen in Modelbinder Global.asax.cs hinzuzufügen.

Dies ist nicht dirrect unswer auf Ihre Frage.

Wir verwenden etwas anderen Ansatz mit dem gleichen Problem lösen Sie haben. Unsere Controller akzeptiert DTOs, die durch Feld persistente Entität Feld entspricht. Dann Benutzer wir AutoMapper persisten Einheiten erstellen, die auf die Datenbank gehen. Dadurch entfällt unnessesery Schnittstellen und sperrt öffentlich zugängliche API (bedeutet, dass persistance Feld des Objekts Umbenennung wird nicht unser Client-Code brechen).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top