রেজারে ডায়নামিক অজ্ঞাতনামা ধরণের কারণে রানটাইমবাইন্ডার এক্সসেপশন হয়


156

আমি নিম্নলিখিত ত্রুটি পাচ্ছি:

'অবজেক্ট' এর মধ্যে 'রেটিংনাম' এর সংজ্ঞা নেই

আপনি যখন বেনামিন গতিশীল প্রকারটি দেখেন, তখন এটি স্পষ্টভাবে রেটিংনাম ধারণ করে।

ত্রুটির স্ক্রিনশট

আমি বুঝতে পারি আমি এটি একটি টিপল দিয়ে করতে পারি, তবে ত্রুটি বার্তাটি কেন ঘটে তা আমি বুঝতে চাই।

উত্তর:


240

আমার মতে বেনামে ধরণের অভ্যন্তরীণ বৈশিষ্ট্যগুলি হ'ল একটি নেট। ফ্রেম ফ্রেম ডিজাইনের সিদ্ধান্ত।

এই সমস্যাটি সমাধানের জন্য এখানে একটি অজানা এবং সুন্দর এক্সটেনশানটি রয়েছে অর্থাত্ বেনামে থাকা অবজেক্টটিকে এখনই একটি ExpandoObject এ রূপান্তর করে।

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> anonymousDictionary =  new RouteValueDictionary(anonymousObject);
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (var item in anonymousDictionary)
        expando.Add(item);
    return (ExpandoObject)expando;
}

এটি ব্যবহার করা খুব সহজ :

return View("ViewName", someLinq.Select(new { x=1, y=2}.ToExpando());

অবশ্যই আপনার দৃষ্টিতে:

@foreach (var item in Model) {
     <div>x = @item.x, y = @item.y</div>
}

2
+1 আমি বিশেষত এইচটিএমএলহেল্পারের সন্ধান করছিলাম onymঅজ্ঞাতনামা অবজেক্টটহএইচটিএমএলঅ্যাট্রিবিউটস আমি জানতাম যে এটি ইতিমধ্যে বেকড করা উচিত এবং অনুরূপ হ্যান্ড্রোলড কোড সহ চাকাটি পুনর্বিবেচনা করতে চাই না।
ক্রিস মেরিসিক

3
কেবল দৃ strongly়ভাবে টাইপ করা ব্যাকিং মডেলটির তুলনায় এর মতো পারফরম্যান্সটি কী?
GONELE

@ ডটনেটওয়াইজ, আপনি যখন এইচটিএমএল হেল্পার ব্যবহার করবেন? অজ্ঞাতনামা অবজেক্টটহএইচটিএমএলটিবুইটস যখন আপনি কেবল আইডিয়োরিয়াল <স্ট্রিং, অবজেক্ট> অজ্ঞাতনামা = নতুন রুটড অভিধান (অবজেক্ট) করতে পারবেন?
জেরেমি বয়ড

আমি এইচটিএমএলহেল্পার.অনামহীনঅবজেক্টটহএইচটিএমএল পরীক্ষা এবং পরীক্ষিত হিসাবে প্রত্যাশিত। আপনার সমাধানটিও কাজ করতে পারে। যেটি সহজ মনে হয় ব্যবহার করুন :)
অ্যাডাপ্টবি

আপনি যদি এটি স্থায়ী সমাধান হিসাবে দেখতে চান তবে আপনি নিজের কন্ট্রোলারে থাকা আচরণকে ওভাররাইড করতে পারেন, তবে এটির জন্য আরও কয়েকটি কাজের প্রয়োজন যেমন বেনামে প্রকারগুলি সনাক্ত করতে সক্ষম হওয়া এবং স্ট্রিং / অবজেক্ট অভিধানটি নিজেই টাইপ থেকে তৈরি করা। যদিও আপনি যদি এটি করেন তবে আপনি এটিকে ওভাররাইড করতে পারেন: সুরক্ষিত ওভাররাইড সিস্টেম. ওয়েবে.এমভিসি.ভিউরসাল্ট ভিউ (স্ট্রিং ভিউনাম, স্ট্রিং মাস্টারনেম, অবজেক্ট মডেল)
জনি স্কোভডাল

50

আমি সম্পর্কিত প্রশ্নের উত্তর খুঁজে পেয়েছি । উত্তরটি ডেভিড এবোয়ের ব্লগ পোস্টে নির্দিষ্ট করা হয়েছে এমভিসি ভিউগুলিতে বেনামে থাকা অবজেক্টগুলি পাস করা এবং গতিশীল ব্যবহার করে সেগুলিতে অ্যাক্সেস করা

এর কারণ হ'ল বেনামে টাইপটি অভ্যন্তরীণভাবে নিয়ামককে দেওয়া হয়, সুতরাং এটি কেবল যে সমাবেশে ঘোষণা করা হয়েছে তার মধ্যেই এটি অ্যাক্সেস করতে পারে। যেহেতু দর্শনগুলি পৃথকভাবে সংকলিত হয়, তাই গতিশীল বাইন্ডার অভিযোগ করে যে এটি সেই সমাবেশের সীমানা পেরিয়ে যেতে পারে না।

তবে আপনি যদি এটির বিষয়ে চিন্তা করেন তবে ডায়নামিক বাইন্ডার থেকে এই বিধিনিষেধটি আসলে বেশ কৃত্রিম, কারণ আপনি যদি ব্যক্তিগত প্রতিচ্ছবি ব্যবহার করেন তবে কোনও কিছুই আপনাকে সেই অভ্যন্তরীণ সদস্যদের অ্যাক্সেস করা থেকে বিরত করছে না (হ্যাঁ, এটি এমনকি মিডিয়াম বিশ্বাসেও কাজ করে)। সুতরাং সিএলআর রানটাইম যা অনুমতি দেয় তা করার পরিবর্তে ডিফল্ট ডায়নামিক বাইন্ডার সি # সংকলন বিধিমালার (যেখানে আপনি অভ্যন্তরীণ সদস্যদের অ্যাক্সেস করতে পারবেন না) প্রয়োগ করার পথে চলে যাচ্ছে।


আমাকে এটাকে মারুন :) আমি আমার রেজার ইঞ্জিন ( razorengine.codeplex.com এর পূর্বসূর ) এর সাথে এই সমস্যায় পড়েছিলাম
বিল্ড স্টার্ট

এটি আসলে কোনও উত্তর নয়, "স্বীকৃত উত্তর" সম্পর্কে আরও কিছু বলছেন না!
আদপতবী

4
@ ডটনেটওয়াইজ: এটি ব্যাখ্যা করে যে ত্রুটি ocurrs কেন, যা ছিল প্রশ্ন। আপনিও একটি সুন্দর কাজের সুযোগ দেওয়ার জন্য আমার উপন্যাস পেয়েছেন :)
লুকাশ

এফওয়াইআই: এই উত্তরটি এখন খুব পুরনো - রেফারেন্স করা ব্লগ পোস্টের শুরুতে লেখক যেমন নিজেকে লাল বলেছিলেন
সাইমন_উইভার

@ সিমন_উইভার তবে এমভিসি 3 + এ এটি কীভাবে কাজ করা উচিত তা পোস্ট আপডেটটি ব্যাখ্যা করে না। - আমি এমভিসি তে একই সমস্যায় পড়েছি dyn বর্তমানে গতিশীল ব্যবহারের 'আশীর্বাদী' উপায়ের কোনও পয়েন্টার?
ক্রিশ্চিয়ান ডায়াকোনস্কু

24

ToExpando পদ্ধতি ব্যবহার করা সবচেয়ে ভাল সমাধান।

এখানে এমন সংস্করণ রয়েছে যার জন্য সিস্টেমের দরকার নেই W ওয়েব সমাবেশ:

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
    {
        var obj = propertyDescriptor.GetValue(anonymousObject);
        expando.Add(propertyDescriptor.Name, obj);
    }

    return (ExpandoObject)expando;
}

1
এটি একটি ভাল উত্তর। বিকল্প উত্তরে আন্ডারস্কোরগুলি সহ এইচটিএমএলহেল্পার কী করে তা নিশ্চিত কিনা তা নিশ্চিত না।
ডেন

সাধারণ উদ্দেশ্যে উত্তরের জন্য +1, এটি এএসপি / এমভিসি
কোডেনহেম

নেস্টেড গতিশীল বৈশিষ্ট্য সম্পর্কে কী? তারা গতিশীল হতে থাকবে ... যেমন: `oo foo:" foo ", নেস্টেড ডায়নামিক: lah ব্লাহ:" ব্লা "lah}
স্পোর্টস

16

বেনামে টাইপ করে কোনও মডেল তৈরি করার পরিবর্তে এবং বেনামে থাকা অবজেক্টটিকে এর ExpandoObjectমতো করে রূপান্তর করার চেষ্টা করা ...

var model = new 
{
    Profile = profile,
    Foo = foo
};

return View(model.ToExpando());  // not a framework method (see other answers)

আপনি কেবল ExpandoObjectসরাসরি তৈরি করতে পারেন :

dynamic model = new ExpandoObject();
model.Profile = profile;
model.Foo = foo;

return View(model);

তারপরে আপনার দৃষ্টিতে আপনি মডেল প্রকারটিকে গতিশীল হিসাবে সেট করেছেন @model dynamicএবং আপনি সরাসরি বৈশিষ্ট্যগুলি অ্যাক্সেস করতে পারবেন:

@Model.Profile.Name
@Model.Foo

আমি বেশিরভাগ দর্শনগুলির জন্য সাধারণত দৃ strongly়ভাবে টাইপ করা ভিউ মডেলগুলির সুপারিশ করতাম তবে কখনও কখনও এই নমনীয়তাটি কার্যকর হয়।


@ ওহাল আপনি অবশ্যই পারবেন - আমার ধারণা এটি ব্যক্তিগত পছন্দ। আমি সাধারণত পৃষ্ঠা মডেলের সাথে সম্পর্কিত নয় বিবিধ পৃষ্ঠাগুলির জন্য ভিউব্যাগটি ব্যবহার করতে পছন্দ করি - সম্ভবত টেমপ্লেটের সাথে সম্পর্কিত এবং মডেলটিকে প্রাথমিক মডেল হিসাবে
রাখুন

2
বিটিডাব্লু আপনাকে ডিফল্ট হিসাবে @ মডেল গতিশীল যুক্ত করতে হবে না
yoel halb

আমার ঠিক কী দরকার ছিল, আনোনকে আপসেটো অবজেক্টে রূপান্তরিত করার পদ্ধতিটি কার্যকর করতে অনেক বেশি সময় নিচ্ছিল ...... ধন্যবাদ স্তূপগুলি
এইচ-রাই

5

আপনি কোনও ইন্টারফেসে একটি বেনামি ধরণের মোড়াতে ফ্রেমওয়ার্ক অপ্রচলিত ইন্টারফেসটি ব্যবহার করতে পারেন ।

আপনি কেবল একটি IEnumerable<IMadeUpInterface>লিঙ্কটি ফেরত চাইবেন এবং আপনার লিনকের শেষে .AllActLike<IMadeUpInterface>();এই কাজটি ব্যবহার করুন কারণ এটি অজ্ঞাতনামা প্রকারের ঘোষিত সমাবেশের প্রসঙ্গে ডিএলআর ব্যবহার করে বেনামে সম্পত্তি বলে।


1
অদ্ভুত ছোট কৌশল :) জানেন না যে এটি সরল শ্রেণীর চেয়ে আরও কিছু ভাল, যদি এই ক্ষেত্রে কমপক্ষে জনসাধারণের সম্পত্তি থাকে ।
অ্যান্ড্রু ব্যাকার

4

একটি কনসোল অ্যাপ্লিকেশন লিখেছে এবং (আপনি এখন থেকে যোগ করতে পারেন রেফারেন্স হিসেবে Mono.Cecil যোগ NuGet ), তারপর কোডের টুকরা লিখুন:

static void Main(string[] args)
{
    var asmFile = args[0];
    Console.WriteLine("Making anonymous types public for '{0}'.", asmFile);

    var asmDef = AssemblyDefinition.ReadAssembly(asmFile, new ReaderParameters
    {
        ReadSymbols = true
    });

    var anonymousTypes = asmDef.Modules
        .SelectMany(m => m.Types)
        .Where(t => t.Name.Contains("<>f__AnonymousType"));

    foreach (var type in anonymousTypes)
    {
        type.IsPublic = true;
    }

    asmDef.Write(asmFile, new WriterParameters
    {
        WriteSymbols = true
    });
}

উপরের কোডটি ইনপুট আরগগুলি থেকে এসেম্বলি ফাইলটি গ্রহণ করবে এবং অভ্যন্তরীণ থেকে অ্যাক্সেসযোগ্যতাটিকে জনসাধারণে পরিবর্তন করতে মনো-সিসিল ব্যবহার করবে এবং এটি সমস্যার সমাধান করবে।

আমরা ওয়েবসাইটটির পোস্ট বিল্ড ইভেন্টে প্রোগ্রামটি চালাতে পারি। আমি চীনা ভাষায় এ সম্পর্কে একটি ব্লগ পোস্ট লিখেছি তবে আমি বিশ্বাস করি আপনি কেবল কোড এবং স্ন্যাপশট পড়তে পারেন। :)


2

গৃহীত উত্তরের ভিত্তিতে, আমি এটিকে সাধারণভাবে এবং পর্দার আড়ালে কাজ করতে কন্ট্রোলারে ওভাররাইড করেছি।

কোডটি এখানে:

protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
    base.OnResultExecuting(filterContext);

    //This is needed to allow the anonymous type as they are intenal to the assembly, while razor compiles .cshtml files into a seperate assembly
    if (ViewData != null && ViewData.Model != null && ViewData.Model.GetType().IsNotPublic)
    {
       try
       {
          IDictionary<string, object> expando = new ExpandoObject();
          (new RouteValueDictionary(ViewData.Model)).ToList().ForEach(item => expando.Add(item));
          ViewData.Model = expando;
       }
       catch
       {
           throw new Exception("The model provided is not 'public' and therefore not avaialable to the view, and there was no way of handing it over");
       }
    }
}

এখন আপনি মডেল হিসাবে কেবল একটি বেনামে জিনিস পাস করতে পারেন, এবং এটি আশানুরূপভাবে কাজ করবে।



0

রানটাইমবাইন্ডার এক্সসেপশনটির কারণ ট্রিগার হয়েছিল, আমি মনে করি অন্যান্য পোস্টগুলিতে ভাল উত্তর আছে। আমি কেবল এটি কীভাবে কাজ করব তা ব্যাখ্যা করার জন্য আমি কেবল মনোনিবেশ করি।

এএসপি.নেট এমভিসিতে বেনামে টাইপ সংগ্রহের সাথে @ ডটনেটওয়াইজ এবং বাঁধাই করা মতামতের উত্তরটি উল্লেখ করে ,

প্রথমত, এক্সটেনশনের জন্য একটি স্ট্যাটিক ক্লাস তৈরি করুন

public static class impFunctions
{
    //converting the anonymous object into an ExpandoObject
    public static ExpandoObject ToExpando(this object anonymousObject)
    {
        //IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject);
        IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
        IDictionary<string, object> expando = new ExpandoObject();
        foreach (var item in anonymousDictionary)
            expando.Add(item);
        return (ExpandoObject)expando;
    }
}

নিয়ামক মধ্যে

    public ActionResult VisitCount()
    {
        dynamic Visitor = db.Visitors
                        .GroupBy(p => p.NRIC)
                        .Select(g => new { nric = g.Key, count = g.Count()})
                        .OrderByDescending(g => g.count)
                        .AsEnumerable()    //important to convert to Enumerable
                        .Select(c => c.ToExpando()); //convert to ExpandoObject
        return View(Visitor);
    }

ভিউতে, @ মডেল আইইনুমেবল (গতিশীল, কোনও মডেল শ্রেণি নয়), এটি অত্যন্ত গুরুত্বপূর্ণ কারণ আমরা বেনামে টাইপ করা অবজেক্টটিকে আবদ্ধ করতে চলেছি।

@model IEnumerable<dynamic>

@*@foreach (dynamic item in Model)*@
@foreach (var item in Model)
{
    <div>x=@item.nric, y=@item.count</div>
}

পূর্বে টাইপ, আমার কাছে ভের বা গতিশীল কোনও ত্রুটি নেই ।

যাইহোক, নতুন ক্ষেত্রের সাথে মিলে যায় এমন একটি নতুন ভিউমোডেল তৈরি করুন ফলাফলটি দর্শনে পাস করার উপায়ও হতে পারে।


0

এখন পুনরাবৃত্তি স্বাদে

public static ExpandoObject ToExpando(this object obj)
    {
        IDictionary<string, object> expandoObject = new ExpandoObject();
        new RouteValueDictionary(obj).ForEach(o => expandoObject.Add(o.Key, o.Value == null || new[]
        {
            typeof (Enum),
            typeof (String),
            typeof (Char),
            typeof (Guid),

            typeof (Boolean),
            typeof (Byte),
            typeof (Int16),
            typeof (Int32),
            typeof (Int64),
            typeof (Single),
            typeof (Double),
            typeof (Decimal),

            typeof (SByte),
            typeof (UInt16),
            typeof (UInt32),
            typeof (UInt64),

            typeof (DateTime),
            typeof (DateTimeOffset),
            typeof (TimeSpan),
        }.Any(oo => oo.IsInstanceOfType(o.Value))
            ? o.Value
            : o.Value.ToExpando()));

        return (ExpandoObject) expandoObject;
    }

0

ExpandoObject এক্সটেনশন ব্যবহার করে নেস্টেড বেনামী অবজেক্ট ব্যবহার করার সময় বিরতি কাজ করে।

যেমন

var projectInfo = new {
 Id = proj.Id,
 UserName = user.Name
};

var workitem = WorkBL.Get(id);

return View(new
{
  Project = projectInfo,
  WorkItem = workitem
}.ToExpando());

এটি সম্পাদন করতে আমি এটি ব্যবহার করি।

public static class RazorDynamicExtension
{
    /// <summary>
    /// Dynamic object that we'll utilize to return anonymous type parameters in Views
    /// </summary>
    public class RazorDynamicObject : DynamicObject
    {
        internal object Model { get; set; }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (binder.Name.ToUpper() == "ANONVALUE")
            {
                result = Model;
                return true;
            }
            else
            {
                PropertyInfo propInfo = Model.GetType().GetProperty(binder.Name);

                if (propInfo == null)
                {
                    throw new InvalidOperationException(binder.Name);
                }

                object returnObject = propInfo.GetValue(Model, null);

                Type modelType = returnObject.GetType();
                if (modelType != null
                    && !modelType.IsPublic
                    && modelType.BaseType == typeof(Object)
                    && modelType.DeclaringType == null)
                {
                    result = new RazorDynamicObject() { Model = returnObject };
                }
                else
                {
                    result = returnObject;
                }

                return true;
            }
        }
    }

    public static RazorDynamicObject ToRazorDynamic(this object anonymousObject)
    {
        return new RazorDynamicObject() { Model = anonymousObject };
    }
}

আপনি ToExpando () এর পরিবর্তে ToRazorDynamic () ব্যবহার না করে নিয়ন্ত্রকের ব্যবহার একই হয়।

সম্পূর্ণ অনামী অবজেক্ট পেতে আপনার দৃষ্টিতে আপনি কেবল শেষে ".অননভ্যালু" যুক্ত করুন।

var project = @(Html.Raw(JsonConvert.SerializeObject(Model.Project.AnonValue)));
var projectName = @Model.Project.Name;

0

আমি ExpandoObject চেষ্টা করেছিলাম তবে এটি নেস্টেড বেনামে জটিল ধরণের সাথে কাজ করে না:

var model = new { value = 1, child = new { value = 2 } };

সুতরাং আমার সমাধানটি ছিল কোনও মডেল দর্শনে JObject ফেরত:

return View(JObject.FromObject(model));

এবং .cshtml এ গতিশীল রূপান্তর করুন:

@using Newtonsoft.Json.Linq;
@model JObject

@{
    dynamic model = (dynamic)Model;
}
<span>Value of child is: @model.child.value</span>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.