2011-11-30 9 views
9

Necesito obtener alguna salida JSON en una secuencia de comandos .NET 2.0 C#. El objetivo es utilizar un método para generar todos los feeds JSON que necesito. Todos los modelos tienen las mismas propiedades de identificación y nombre, así que tengo alrededor de 15 espacios de nombres que tienen las mismas partes aquí. En resumen: ya que soy el uso castillo puedo llamar a la función como:¿Cómo puedo usar un argumento de cadena para guardar un espacio de nombre o tipo?

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

Qué en el castillo está llamando cada método, es decir: la get_place_tags(){} pero quiero no tener que trabajar donde pueda llamar a un método obtener salida de cada tipo como este:

/public/get_json.castle?wantedtype=place_types 

¿Alguien sabe cómo solucionar esto?

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); 
     } 
    } 
} 

[EDIT] - (la más reciente Idea) la creación de tipo de tiempo de ejecución .. Esto creo que es la idea más limpio en una manera de conseguir que funcione ...-----

Entonces, el objetivo es realmente tener en tiempo de ejecución un tipo utilizado ... correcto ... así que pensé que esto funcionaría. http://www.java2s.com/Code/CSharp/Development-Class/Illustratesruntimetypecreation.htm y basado en que aquí está el método hasta ahora. Todavía tengo problemas para obtener t para pasar el error "No se pudo encontrar el tipo o el nombre del espacio de nombres 't' (¿falta una directiva using o una referencia de ensamblado?)" ... no estoy seguro de a dónde voy mal aquí. Parece que no puede conseguir nada de ella para trabajar lol ..

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] - (idea más antigua) código de Eval -----

Así que este intento de hacer que esto suceda es utilizar la reflexión y cosas que hacer una eval de clases en base a este 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 
    } 

sé que se sugirió que el uso no es necesaria .. sé que no los conozco de la parte superior y tal vez eso está mostrando el nivel ... Pero aquí están para lo que creo que funcionará solo encima.

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; 
+1

Por favor, solo publique el código correspondiente. 'usar' es inútil para las personas que intentan ayudarlo. – Otiel

+0

¿Cómo conseguimos que la gente vea esto para esto? –

+3

Ver el [faq] (http://stackoverflow.com/faq#bounty). – Otiel

Respuesta

0

Me cansé y probé y me cansé de una de estas maneras. A mí y a un compañero de trabajo se nos ocurrió una solución. Hice 2 archivos.

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); 
     } 
    } 
} 

entonces cuando llamé a la función de la url esto es lo que terminó como

 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()); 
     } 

y uno fuera los modelos

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; } 
     } 

    } 
} 

ahora cuando se llama a

/public/get_json.castle?wantedtype=place_types 

o

/public/get_json.castle?wantedtype=place_tags 

Usted obtendrá la salida JSON de cada modelo. Tada! : D Gracias a todos por ayudar.

1

Bueno, esto es sólo una sugerencia, y no sé nada sobre el castillo, pero me parece que usted está queriendo una ruta personalizada.

Esto no se ha probado y, por supuesto, tendrá que ajustar, pero echar un vistazo a su método de Global.asax RegisterRoutes y añadir esta por encima de usted omite ruta

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

algo como esto puede ser que consiga lo que está después .

es posible que tenga que jugar con la acción para que coincida con su marco de castillo

EDITAR

que tenía un poco más de tiempo para mirar esto.El uso de la ruta que he descrito anteriormente y el siguiente método en el controlador Me dieron un buen resultado

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 obras, esta URL no funciona http://.../Public/Int32

Ahora bien, si desea utilizar la versión corta podría usar algo como MEF o AutoFAC o Castle para hacer una búsqueda en su contenedor para el tipo que busca.

Así que mi respuesta es utilizar una buena ruta para obtener la clave para el tipo deseado y luego crear una fábrica para administrar las asignaciones de tipos y producir una instancia de lo que está buscando.

+0

Lo siento, pero creo que está lejos. No quiero una ruta url personalizada. Quiero usar un argumento de cadena para mayúsculas y minúsculas, o escriba como dice el título. En pocas palabras, necesito un tipo dinámico en C# .net 2.0. Gracias por intentarlo –

+0

Hice una pequeña maqueta y pude obtener un System.Int32 del código que agregué a mi sugerencia original – Peter

+0

caslte ya maneja la ruta como se muestra en el código anterior, por lo que no es necesario. Notarás que no pasó System.Int32 ni ningún otro FullyQuailfiedName, así que en el código original terminaste con el mismo código que dije que no funcionaba. Si puede mostrar un ejemplo donde es un tipo deseado == , es decir: terminando con ya que el tipo t es igual a arg wantedtype, permitiendo que el registro activo se mueva a través del objeto tipeado, entonces foreach (place_types place_type in types) luego funciona. Como se muestra el primer método, funciona, solo necesito hacer que el sea dinámico. Espero que eso lo aclare. –

1

acabo de tener un vistazo a la ActiveRecord API Doco Here

Hay un método FindAll (Tipo targetType): Array

has necesitado reemplazar

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

con

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

no probado por completo pero vea lo que piensa

+0

um ... No estoy al 100% aquí, pero no creo que la cámara dinámica salga hasta 3.5 y esto es 2.0 .. Lo intentaré tk. -J –

+0

Creo que el bit importante es usar ActiveRecordBase.FindAll (t); y si la dinámica no funciona, use var all_tag = ActiveRecordBase.FindAll (t); también debería considerar la actualización a .NET 4 si es posible – Peter

+0

: D, lo siento, pero la actualización a 4.0+ no está sucediendo, y ActiveRecordBase.FindAll() es el que crea el objeto a través de la base de datos. eso debería explicar el error en ActiveRecordBase.FindAll (t) de "Error 79 'Castle.ActiveRecord.ActiveRecordBase.FindAll (System.Type, NHibernate.Expression.DetachedCriteria, params NHibernate.Expression.Order [])' es inaccesible debido a su nivel de protección "también para la dinámica obtengo el error esperado también de" Error 78 No se pudo encontrar el tipo o el nombre del espacio de nombres 'dynamic' (¿falta una directiva using o una referencia de ensamblado?) ".. –

Cuestiones relacionadas