Как я могу использовать строковый аргумент для определения пространства имен или типа? - PullRequest
9 голосов
/ 01 декабря 2011

Мне нужно получить вывод JSON в скрипте .NET 2.0 C #. Цель состоит в том, чтобы использовать один метод для вывода всех нужных мне фидов JSON. Все модели имеют одинаковые свойства идентификатора и имени, поэтому у меня есть около 15 пространств имен, которые имеют одинаковые части. Вкратце: так как я использую замок, я могу вызвать функцию как:

/public/get_place_tags.castle
/public/get_place_types.castle
/public/get_place_whichEver.castle

Который в замке вызывает каждый метод, т. Е. get_place_tags(){}, но мне не нужно работать, когда я могу вызвать один метод для получения выходных данных от каждого типа, например:

/public/get_json.castle?wantedtype=place_types

Кто-нибудь знает, как это исправить?

namespace campusMap.Controllers
{
    [Layout("home")]
    public class PublicController : BaseController
    {
        /*  works and returns */
        public void get_pace_type()
        {
            CancelView();
            CancelLayout();

            place_types[] types = ActiveRecordBase<place_types>.FindAll();
            List<JsonAutoComplete> type_list = new List<JsonAutoComplete>();

            foreach (place_types place_type in types)
            {
                JsonAutoComplete obj = new JsonAutoComplete();

                obj.id = place_type.place_type_id;
                obj.label = place_type.name;
                obj.value = place_type.name;

                type_list.Add(obj);
            }

            string json = JsonConvert.SerializeObject(type_list);
            RenderText(json);
        }

        /*  can;t ever find the namespace */
        public void get_json(string wantedtype)
        {
            CancelView();
            CancelLayout();
            Type t = Type.GetType(wantedtype); 

            t[] all_tag = ActiveRecordBase<t>.FindAll();
            List<JsonAutoComplete> tag_list = new List<JsonAutoComplete>();

            foreach (t tag in all_tag)
            {
                JsonAutoComplete obj = new JsonAutoComplete();

                obj.id = tag.id;
                obj.label = tag.name;
                obj.value = tag.name;

                tag_list.Add(obj);
            }

            string json = JsonConvert.SerializeObject(tag_list);
            RenderText(json);
        }
    }
}

[РЕДАКТИРОВАТЬ] - (Новейшая идея) Создание типа среды выполнения. Я думаю, что это самая чистая идея для того, чтобы заставить его работать ...-----

Так что цель в действительности состоит в том, чтобы во время выполнения использовать используемый тип ... верно ... поэтому я подумал, что это сработает. http://www.java2s.com/Code/CSharp/Development-Class/Illustratesruntimetypecreation.htm и основанный на этом здесь метод пока. У меня все еще есть проблемы с получением t чтобы обойти ошибку "Не удалось найти тип или имя пространства имен 't' (вы пропустили директиву using или ссылку на сборку?)" .. не уверен, где я ошибаюсь. Кажется, я не могу заставить его работать ... 1018 *

public void get_json(String TYPE)
{
    CancelView();
    CancelLayout();
    if (String.IsNullOrEmpty(TYPE))
    {
        TYPE = "place_types";
    }
    // get the current appdomain
    AppDomain ad = AppDomain.CurrentDomain;

    // create a new dynamic assembly
    AssemblyName an = new AssemblyName();
    an.Name = "DynamicRandomAssembly";
    AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);

    // create a new module to hold code in the assembly
    ModuleBuilder mb = ab.DefineDynamicModule("RandomModule");

    // create a type in the module
    TypeBuilder tb = mb.DefineType(TYPE, TypeAttributes.Public);

    // finish creating the type and make it available
    Type t = tb.CreateType();
    t[] all_tag = ActiveRecordBase<t>.FindAll();

    List<JsonAutoComplete> tag_list = new List<JsonAutoComplete>();
    foreach (t tag in all_tag)
    {
        JsonAutoComplete obj = new JsonAutoComplete();
        obj.id = tag.id;
        obj.label = tag.name;
        obj.value = tag.name;
        tag_list.Add(obj);
    }
    RenderText(JsonConvert.SerializeObject(tag_list)); 
}

[EDIT] - (Старая идея) Eval код -----

Таким образом, эта попытка сделать это состоит в том, чтобы использовать рефлексию и прочее, чтобы сделать что-то вроде оценки, основанной на этом http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=11939

namespace EvalCSCode
{
    /// <summary>
    /// Interface that can be run over the remote AppDomain boundary.
    /// </summary>
    public interface IRemoteInterface
    {
        object Invoke(string lcMethod, object[] Parameters);
    }


    /// <summary>
    /// Factory class to create objects exposing IRemoteInterface
    /// </summary>
    public class RemoteLoaderFactory : MarshalByRefObject
    {
        private const BindingFlags bfi = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;

        public RemoteLoaderFactory() { }

        /// <summary> Factory method to create an instance of the type whose name is specified,
        /// using the named assembly file and the constructor that best matches the specified parameters. </summary>
        /// <param name="assemblyFile"> The name of a file that contains an assembly where the type named typeName is sought. </param>
        /// <param name="typeName"> The name of the preferred type. </param>
        /// <param name="constructArgs"> An array of arguments that match in number, order, and type the parameters of the constructor to invoke, or null for default constructor. </param>
        /// <returns> The return value is the created object represented as ILiveInterface. </returns>
        public IRemoteInterface Create(string assemblyFile, string typeName, object[] constructArgs)
        {
            return (IRemoteInterface)Activator.CreateInstanceFrom(
                assemblyFile, typeName, false, bfi, null, constructArgs,
                null, null, null).Unwrap();
        }
    }
}


#endregion
namespace campusMap.Controllers
{

    public class JsonAutoComplete
    {
        private int Id;
        [JsonProperty]
        public int id
        {
            get { return Id; }
            set { Id = value; }
        }
        private string Label;
        [JsonProperty]
        public string label
        {
            get { return Label; }
            set { Label = value; }
        }
        private string Value;
        [JsonProperty]
        public string value
        {
            get { return Value; }
            set { Value = value; }
        }
    }


    [Layout("home")]
    public class publicController : BaseController
    {
        #region JSON OUTPUT
        /*  works and returns */
        public void get_pace_type()
        {
            CancelView();
            CancelLayout();
            place_types[] types = ActiveRecordBase<place_types>.FindAll();

            List<JsonAutoComplete> type_list = new List<JsonAutoComplete>();
            foreach (place_types place_type in types)
            {
                JsonAutoComplete obj = new JsonAutoComplete();
                obj.id = place_type.id;
                obj.label = place_type.name;
                obj.value = place_type.name;
                type_list.Add(obj);
            }
            string json = JsonConvert.SerializeObject(type_list);
            RenderText(json);
        }
        /*  how I think it'll work to have a dynmaic type */
        public void get_json(string type)
        {
            CancelView();
            CancelLayout();
            /*t[] all_tag = ActiveRecordBase<t>.FindAll();

            List<JsonAutoComplete> tag_list = new List<JsonAutoComplete>();
            foreach (t tag in all_tag)
            {
                JsonAutoComplete obj = new JsonAutoComplete();
                obj.id = tag.id;
                obj.label = tag.name;
                obj.value = tag.name;
                tag_list.Add(obj);
            }*/
            StringBuilder jsonobj = new StringBuilder("");
            jsonobj.Append(""+type+"[] all_tag = ActiveRecordBase<"+type+">.FindAll();\n");
            jsonobj.Append("List<JsonAutoComplete> tag_list = new List<JsonAutoComplete>();{\n");
            jsonobj.Append("foreach ("+type+" tag in all_tag){\n");
            jsonobj.Append("JsonAutoComplete obj = new JsonAutoComplete();\n");
            jsonobj.Append("obj.id = tag.id;\n");
            jsonobj.Append("obj.label = tag.name;\n");
            jsonobj.Append("obj.value = tag.name;\n");
            jsonobj.Append("tag_list.Add(obj);\n");
            jsonobj.Append("}\n");

            CSharpCodeProvider c = new CSharpCodeProvider();
            ICodeCompiler icc = c.CreateCompiler();
            CompilerParameters cp = new CompilerParameters();

            cp.ReferencedAssemblies.Add("system.dll");
            cp.ReferencedAssemblies.Add("Newtonsoft.Json.Net20.dll");
            cp.ReferencedAssemblies.Add("Castle.ActiveRecord.dll");

            cp.CompilerOptions = "/t:library";
            cp.GenerateInMemory = true;

            StringBuilder sb = new StringBuilder("");
            sb.Append("namespace CSCodeEvaler{ \n");
            sb.Append("public class CSCodeEvaler{ \n");
            sb.Append("public object EvalCode(){\n");
            sb.Append("return " + jsonobj + "; \n");
            sb.Append("} \n");
            sb.Append("} \n");
            sb.Append("}\n");

            CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
            System.Reflection.Assembly a = cr.CompiledAssembly;
            object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");

            Type t = o.GetType();
            MethodInfo mi = t.GetMethod("EvalCode");

            object s = mi.Invoke(o, null); 

            string json = JsonConvert.SerializeObject(s);
            RenderText(json);
        }/**/
        #endregion
   }

Я знаю, что было высказано предположение, что использование не нужно ... Я знаю, что не знаю их сверху и, возможно, это уровень показывает .. Но здесь они для того, что я думаю, будет работать чуть выше.

using System;
using System.Collections;
using System.Collections.Generic;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Queries;
using Castle.MonoRail.Framework;
using Castle.MonoRail.ActiveRecordSupport;
using campusMap.Models;
using MonoRailHelper;
using System.IO;
using System.Net;
using System.Web;
using NHibernate.Expression;
using System.Xml;
using System.Xml.XPath;
using System.Text.RegularExpressions;
using System.Text;
using System.Net.Sockets;
using System.Web.Mail;
using campusMap.Services;


using Newtonsoft.Json;
using Newtonsoft.Json.Utilities;
using Newtonsoft.Json.Linq;

using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.IO;
using System.Threading;
using System.Reflection;

Ответы [ 3 ]

1 голос
/ 09 декабря 2011

Я только что посмотрел на ActiveRecord API Doco Здесь

Есть метод FindAll (Тип targetType): Array

Вы пытались заменить

 Type t = Type.GetType(wantedtype); 
 t[] all_tag = ActiveRecordBase<t>.FindAll();
 // blah blah blah

с

Type t = Type.GetType(wantedtype); 
dynamic all_tag = ActiveRecordBase.FindAll(t);
RenderText(JsonConvert.SerializeObject(all_tag ));

полностью не проверено, но посмотрите, что вы думаете

1 голос
/ 07 декабря 2011

Хорошо, это всего лишь предложение, и я ничего не знаю о замке, но мне кажется, что вы хотите собственный маршрут.

Это не проверено, и, конечно, вам придется его настроить, ноПосмотрите на ваш метод Global.asax RegisterRoutes и добавьте его выше вашего маршрута по умолчанию

        routes.MapRoute(
            "TypeRoute", // Route name
            "Public/{wantedtype}", // URL with parameters
            new { controller = "Public", action = "get_json", wantedtype = UrlParameter.Optional } // Parameter defaults
        );

что-то вроде этого может получить то, что вы ищете.

вам может понадобиться возиться с действиемэто соответствует вашей структуре замка

РЕДАКТИРОВАТЬ

У меня было еще немного времени, чтобы посмотреть на это.Используя маршрут, который я описал выше, и следующий метод на контроллере, я получил хороший результат

    public void get_json(string wantedtype)
    {
        Type t = Type.GetType(wantedtype);
        // t.Name = "Int32" when "System.Int32 is used as the wanted type
    }

http: //.../Public/System.Int32 работает, этот URLне работает http: //.../Public/Int32

Теперь, если вы хотите использовать короткую версию, вы можете использовать что-то вроде MEF, AutoFAC или Castle для поискав вашем контейнере для типа вы после.

Поэтому мой ответ - использовать хороший маршрут, чтобы получить ключ для требуемого типа, затем построить фабрику для управления отображениями типов и создать экземпляр того, что вам нужно.

0 голосов
/ 20 января 2012

Я устал и пытался и устал от одного из этих способов. Я и сотрудник придумали это решение. Я сделал 2 файла.

Ijson_autocomplete.cs

using System;
namespace campusMap.Models
{
    public interface Ijson_autocomplete
    {
        int id { get; set; }
        string name { get; set; }
        String get_json_data();
    }
}

json_autocomplete.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Castle.ActiveRecord;
using System.Collections.Generic;
using System.Data.SqlTypes;
using Newtonsoft.Json;
using Newtonsoft.Json.Utilities;
using Newtonsoft.Json.Linq;



namespace campusMap.Models
{

    public class JsonAutoComplete
    {
        private int Id;
        [JsonProperty]
        public int id
        {
            get { return Id; }
            set { Id = value; }
        }
        private string Label;
        [JsonProperty]
        public string label
        {
            get { return Label; }
            set { Label = value; }
        }
        private string Value;
        [JsonProperty]
        public string value
        {
            get { return Value; }
            set { Value = value; }
        }
    }
    public class json_autocomplete<t> where t : campusMap.Models.Ijson_autocomplete
    {

        virtual public String get_json_data()
        {
            t[] all_tag = ActiveRecordBase<t>.FindAll();
            List<JsonAutoComplete> tag_list = new List<JsonAutoComplete>();
            foreach (t tag in all_tag)
            {
                JsonAutoComplete obj = new JsonAutoComplete();
                obj.id = tag.id;
                obj.label = tag.name;
                obj.value = tag.name;
                tag_list.Add(obj);
            }
            return JsonConvert.SerializeObject(tag_list);
        }
    }
}

тогда, когда я вызвал функцию из URL, это то, что в итоге получилось как

        public void get_json(String TYPE)
        {
            CancelView();
            CancelLayout();
            Type t = Type.GetType("campusMap.Models."+TYPE);
            Ijson_autocomplete theclass = (Ijson_autocomplete)Activator.CreateInstance(t);
            RenderText(theclass.get_json_data());
        }

и одна модель

namespace campusMap.Models
{
    [ActiveRecord(Lazy=true)]
    public class place_types : json_autocomplete<place_types>, campusMap.Models.Ijson_autocomplete
    {
        private int place_type_id;
        [PrimaryKey("place_type_id")]
        virtual public int id
        {
            get { return place_type_id; }
            set { place_type_id = value; }
        }

        private string Name;
        [Property]
        virtual public string name
        {
            get { return Name; }
            set { Name = value; }
        }

        private string Attr;
        [Property]
        virtual public string attr
        {
            get { return Attr; }
            set { Attr = value; }
        }
        private IList<place> places;
        [HasAndBelongsToMany(typeof(place), Lazy = true, Table = "place_to_place_models", ColumnKey = "place_model_id", ColumnRef = "place_id", Inverse = true, NotFoundBehaviour = NotFoundBehaviour.Ignore)]
        virtual public IList<place> Places
        {
            get { return places; }
            set { places = value; }
        }

    }
}

теперь, когда вы звоните

/public/get_json.castle?wantedtype=place_types

или

/public/get_json.castle?wantedtype=place_tags

Вы получите вывод json для каждой модели. Тада! : D Спасибо всем за помощь.

...