कंट्रोलर में प्रवेश करने के बाद लेट बाइ डायनामिकली रिजॉल्यूशन मॉडल्स


9

मैं एक नियंत्रक में एक कार्रवाई में प्रवेश करने के बाद एक मॉडल को हल करने का एक तरीका ढूंढ रहा हूं, समस्या का वर्णन करने का सबसे सरल तरीका होगा:

public DTO[] Get(string filterName)
{
    //How can I do this
    this.Resolve<MyCustomType>("MyParamName");
}

यदि आप इस बारे में अधिक जानकारी की तलाश कर रहे हैं कि मैं ऐसा क्यों करना चाह रहा हूं तो आप पूरी तस्वीर पाने के लिए पढ़ना जारी रख सकते हैं

टी एल; डॉ

मैं एक मॉडल को एक अनुरोध को हल करने का एक तरीका ढूंढ रहा हूं, एक पैरामीटर नाम दिया गया है जो हमेशा क्वेरी स्ट्रिंग से हल किया जाएगा मैं स्टार्टअप से फ़िल्टर को गतिशील रूप से कैसे पंजीकृत कर सकता हूं। मेरे पास एक वर्ग है जो मेरे फ़िल्टर को पंजीकृत करने का काम करने वाला है।

अपने स्टार्टअप क्लास में मैं अपने रेस्ट सर्विसेज के साथ फिल्टर को गतिशील रूप से पंजीकृत करने में सक्षम होना चाहता हूं। मेरे पास एक विकल्प है जो मैं अपने कस्टम कंट्रोलर के पास जाने के लिए उपयोग कर रहा हूं। Piderider जो लगभग ऐसा दिखता है:

public class DynamicControllerOptions<TEntity, TDTO>
{
    Dictionary<string, Func<HttpContext, Expression<Func<TEntity, bool>>>> _funcNameToEndpointResolverMap
        = new Dictionary<string, Func<HttpContext, Expression<Func<TEntity, bool>>>>();
    Dictionary<string, List<ParameterOptions>> _filterParamsMap = new Dictionary<string, List<ParameterOptions>>();

    public void AddFilter(string filterName, Expression<Func<TEntity, bool>> filter)
    {
        this._funcNameToEndpointResolverMap.Add(filterName, (httpContext) =>  filter);
    }
    public void AddFilter<T1>(string filterName, Func<T1, Expression<Func<TEntity, bool>>> filterResolver,
        string param1Name = "param1")
    {
        var parameters = new List<ParameterOptions> { new ParameterOptions { Name = param1Name, Type = typeof(T1) } };
        this._filterParamsMap.Add(filterName, parameters);
        this._funcNameToEndpointResolverMap.Add(filterName, (httpContext) => {
            T1 parameter = this.ResolveParameterFromContext<T1>(httpContext, param1Name);
            var filter = filterResolver(parameter);
            return filter;
        });
    }
}

मेरा नियंत्रक विकल्पों का ट्रैक रखेगा और पेजिंग एंडपॉइंट्स और ओडाटा के लिए फिल्टर प्रदान करने के लिए उनका उपयोग करेगा।

public class DynamicControllerBase<TEntity, TDTO> : ControllerBase
{
    protected DynamicControllerOptions<TEntity, TDTO> _options;
    //...

    public TDTO[] GetList(string filterName = "")
    {
        Expression<Func<TEntity, bool>> filter = 
            this.Options.ResolveFilter(filterName, this.HttpContext);
        var entities = this._context.DbSet<TEntity>().Where(filter).ToList();
        return entities.ToDTO<TDTO>();
    }
}

मुझे यह पता लगाने में कठिनाई हो रही है कि HttpContext को दिए गए मॉडल को गतिशील रूप से कैसे हल किया जाए, मैं मॉडल प्राप्त करने के लिए कुछ ऐसा करने के लिए सोचूंगा लेकिन यह छद्म कोड है जो काम नहीं करता है

private Task<T> ResolveParameterFromContext<T>(HttpContext httpContext, string parameterName)
{
    //var modelBindingContext = httpContext.ToModelBindingContext();
    //var modelBinder = httpContext.Features.OfType<IModelBinder>().Single();
    //return modelBinder.BindModelAsync<T>(parameterName);
}

स्रोत में खुदाई करने के बाद, मैंने कुछ आशाजनक चीजें देखीं ModelBinderFactory और नियंत्रकअभियोजनइंवर इन वर्गों का उपयोग मॉडल बाइंडिंग के लिए पाइपलाइन में किया जाता है,

मैं इस तरह से कुछ, क्वेरीरीरिंग से एक पैरामीटर नाम को हल करने के लिए एक सरल इंटरफ़ेस को उजागर करने की उम्मीद करूंगा:

ModelBindingContext context = new ModelBindingContext();
return context.GetValueFor<T>("MyParamName");

हालांकि, मॉडल बाइंडर से एक मॉडल को हल करने का एकमात्र तरीका मुझे नकली नियंत्रक विवरण बनाने और एक टन चीजों को मॉक करने का है।

मैं अपने कॉनोलर में देर से बाध्य मापदंडों को कैसे स्वीकार कर सकता हूं?


2
मुझे इसके लिए कोई उपयोग नहीं दिख रहा है। इसके अलावा, भले ही आप एक स्ट्रिंग पैरामीटर के आधार पर मॉडल को बांध सकते हैं .... आप GetValueFor <T> जैसी सामान्य विधि का उपयोग नहीं कर पाएंगे क्योंकि टी को एक संकलन समय हल किया जाना चाहिए .... इसका मतलब है कि कॉलर को पता होना चाहिए संकलन के समय टी का प्रकार जो गतिशील रूप से बाध्यकारी प्रकार के उद्देश्य को हरा देगा। इसका मतलब है कि डायनेमिककंट्रोलरबेस के उत्तराधिकारी को टीडीटीओ के प्रकार का पता होना चाहिए। .... एक चीज जो आप आजमा सकते हैं, वह पैरामीटर में जेएसएन प्राप्त कर सकता है और डायनेमिककंट्रोलरबेस के प्रत्येक कार्यान्वयन में एक मॉडल और वाइसवर्स के लिए स्ट्रिंग को deserialize है।
जोनाथन अल्फारो

@Darkonekt यदि आप 'AddFilter' विधि को देखते हैं, तो आपके पास टाइप किए गए जेनेरिक पैरामीटर हैं, जो फ़न को पंजीकृत करते समय एक क्लोजर में संग्रहीत हो जाते हैं। यह थोड़ा भ्रमित करने वाला है लेकिन मैं आपको इसके व्यवहार्य होने का आश्वासन देता हूं और काम कर सकता हूं
जॉनी 5

मैं जोंस में प्लग नहीं करना चाहता, क्योंकि मैं नहीं चाहता कि वेबैपी के तरीके को स्वाभाविक रूप से मापदंडों को बदलना पड़े
जॉनी 5

यदि आप उपयोग के मामले और वास्तविक जीवन परिदृश्य के बारे में थोड़ा और समझाते हैं जहाँ इस तरह की कार्यक्षमता आवश्यक है, तो इससे बहुत मदद मिलेगी। शायद वहाँ भी एक सरल समाधान उपलब्ध है .. कौन जानता है। अपने स्वयं के लिए, मैं कभी-कभी चीजों को जटिल करना पसंद करता हूं .. बस कह रहा हूं ..
श्री ब्लॉन्ड

@ Mr.Blond मेरे पास एक जेनेरिक रेस्ट सर्विस है जो क्रूड प्रदान करती है और सूची कार्यक्षमता प्राप्त करती है। कभी-कभी मेरी सेवाओं को सूची प्राप्त करने से डेटा को फ़िल्टर करने की आवश्यकता होती है, लेकिन मैं एक फिल्टर प्रदान करने के लिए सभी की पूरी सेवा लिखना नहीं चाहता हूं
जॉनी 5

जवाबों:


2

मैं आपके विचार से सहमत हूं

सेवाओं को सूची प्राप्त करने से डेटा को फ़िल्टर करने की आवश्यकता होती है, लेकिन मैं एक फ़िल्टर प्रदान करने के लिए सभी की पूरी सेवा लिखना नहीं चाहता

हर संभावित संयोजन के लिए एक विजेट / फ़िल्टर / समापन बिंदु क्यों लिखें?

सभी डेटा / प्रॉपर्टी पाने के लिए बस मूल संचालन प्रदान करें। फिर अंतिम उपयोगकर्ता को उनकी आवश्यकताओं को फ़िल्टर ( मॉडल ) करने के लिए अनुमति देने के लिए ग्राफ़कॉल का उपयोग करें ।

से GraphQL

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools


मैं ग्राफ़कैल का उपयोग करने पर विचार कर रहा हूं, लेकिन मैं अपने वर्तमान कार्यान्वयन में शामिल हूं
जॉनी 5

2

हमने ऐसा किया है, हमारा कोड इस साइट को संदर्भित करता है: https://prideparrot.com/blog/archive/2012/6/gotchas_in_explicit_model_binding

विशेष रूप से, हमारे कोड को देखकर, क्या चाल आपके नियंत्रक विधि में एक FormCollection को स्वीकार कर रही है और फिर मॉडल बाइंडर, मॉडल और फॉर्म डेटा का उपयोग कर रही है:

लिंक से लिया गया उदाहरण:

public ActionResult Save(FormCollection form)
{
var empType = Type.GetType("Example.Models.Employee");
var emp = Activator.CreateInstance(empType);

var binder = Binders.GetBinder(empType);

  var bindingContext = new ModelBindingContext()
  {
    ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => emp, empType),
    ModelState = ModelState,
    ValueProvider = form
  };      

  binder.BindModel(ControllerContext, bindingContext);

  if (ModelState.IsValid)
  {
   _empRepo.Save(emp);

    return RedirectToAction("Index");
  }

return View();
}

(नोट: साइट नीचे दिखती है, लिंक आर्काइव डॉट ओआरजी पर है)


आपकी मदद के लिए धन्यवाद, वर्तमान में, मैं एमवीसी का उपयोग नहीं कर रहा हूं, जैसे (1 इनपुट पैरामीटर से अधिक हो सकता है) मुझे नाम से मापदंडों को हल करने की आवश्यकता है। इसके अतिरिक्त मैं .Net-Core का उपयोग कर रहा हूं, मुझे लगता है कि यह पुराने संस्करण .net के लिए लिखा गया है। कृपया इस विधि को पूरा करें: स्वीकार किए जाने वाले उत्तर के लिए:this.Resolve<MyCustomType>("MyParamName");
जॉनी 5

चूँकि मेरे पास इसे न्यूनतम रूप से पुन: पेश करने का वातावरण नहीं है, इसलिए मैं ऐसा नहीं कर पाऊँगा - मैं डॉटनेटकोर आवश्यकता को याद करने के लिए क्षमा चाहता हूँ।
ब्रायन का कहना है कि मोनिका

मैं इसका अनुवाद कर सकता हूं। नेट-कोर यह ठीक है, अगर आप मुझे दिखाते हैं कि कैसे पैरामीटर नाम से हल करना है तो मैं स्वीकार करूंगा
जॉनी 5

यह जवाब के लिए सबसे करीबी बात है जो मैं चाहता था ताकि मैं आपको इनाम दे दूं
जॉनी 5

0

मैंने डायनेमिक कंट्रोलर्स लिखना समाप्त कर दिया। समस्या को काम के रूप में हल करने के लिए।

private static TypeBuilder GetTypeBuilder(string assemblyName)
{
    var assemName = new AssemblyName(assemblyName);
    var assemBuilder = AssemblyBuilder.DefineDynamicAssembly(assemName, AssemblyBuilderAccess.Run);
    // Create a dynamic module in Dynamic Assembly.
    var moduleBuilder = assemBuilder.DefineDynamicModule("DynamicModule");
    var tb = moduleBuilder.DefineType(assemblyName,
            TypeAttributes.Public |
            TypeAttributes.Class |
            TypeAttributes.AutoClass |
            TypeAttributes.AnsiClass |
            TypeAttributes.BeforeFieldInit |
            TypeAttributes.AutoLayout,
            null);

    return tb;
}

मैं अभी के लिए विधि में फ़न कोडिंग को कठिन बना रहा हूं, लेकिन मुझे यकीन है कि आप ज़रूरत पड़ने पर इसका पता लगा सकते हैं।

public static Type CompileResultType(string typeSignature)
{
    TypeBuilder tb = GetTypeBuilder(typeSignature);

    tb.SetParent(typeof(DynamicControllerBase));

    ConstructorBuilder ctor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

    // For this controller, I only want a Get method to server Get request
    MethodBuilder myGetMethod =
        tb.DefineMethod("Get",
            MethodAttributes.Public,
            typeof(String), new Type[] { typeof(Test), typeof(String) });

    // Define parameters
    var parameterBuilder = myGetMethod.DefineParameter(
        position: 1, // 0 is the return value, 1 is the 1st param, 2 is 2nd, etc.
        attributes: ParameterAttributes.None,
        strParamName: "test"
    );
    var attributeBuilder
        = new CustomAttributeBuilder(typeof(FromServicesAttribute).GetConstructor(Type.EmptyTypes), Type.EmptyTypes);
    parameterBuilder.SetCustomAttribute(attributeBuilder);

    // Define parameters
    myGetMethod.DefineParameter(
        position: 2, // 0 is the return value, 1 is the 1st param, 2 is 2nd, etc.
        attributes: ParameterAttributes.None,
        strParamName: "stringParam"
    );

    // Generate IL for method.
    ILGenerator myMethodIL = myGetMethod.GetILGenerator();
    Func<string, string> method = (v) => "Poop";

    Func<Test, string, string> method1 = (v, s) => v.Name + s;

    myMethodIL.Emit(OpCodes.Jmp, method1.Method);
    myMethodIL.Emit(OpCodes.Ret);

    return tb.CreateType();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.