2010-07-24 11 views
5

Cómo registrar un caso en el archivo de configuraciónregistrar una instancia de configuración con la Unidad

estoy teniendo este código:

UnityContainer.RegisterInstance<ICache>(new CacheMng(HttpRuntime.Cache)); 

y tratando de tener el equivalente de un archivo de configuración

<register type="ICache" mapTo="CacheMng"> 
    <lifetime type="Singleton"/> 
    <constructor> 
     <param name="cache" type="System.Web.Caching" value="HttpRuntime.Cache"/> 
    </constructor>> 
</register> 

Mi clase CacheMng tiene este constructor

public CacheMng(Cache cache) 
{ 
    this._cache = cache 
} 

que estoy recibiendo este error

El nombre del tipo o System.Web.Caching alias no se podían resolver

Respuesta

3

La razón por la que recibe el mensaje de error que se ve es que el parámetro requiere un type escriba el nombre y no un nombre de espacio de nombres. System.Web.Caching es un espacio de nombres y no un tipo.

La única manera de hacer esto es escribir un convertidor de tipo personalizado y utilizar el elemento value, así:

<constructor> 
    <param name="cache"> 
     <value value="" typeConverter="MyHttpRuntimeCacheConverter" /> 
    </param> 
</constructor> 

El convertidor de tipos se ve algo como esto (en su forma más simple):

public class MyHttpRuntimeCacheConverter : System.ComponentModel.TypeConverter 
{ 
    public override object ConvertTo(ITypeDescriptorContext context, 
            CultureInfo culture, object value, 
            Type destinationType) 
    { 
     return HttpRuntime.Cache; 
    } 
} 

Puede hacer que esto sea más aplicable en general proporcionando realmente un valor para el elemento Unity value (por ejemplo: System.Web.HttpRuntime.Cache) y en base a este valor haga que el convertidor de tipo devuelva el objeto correcto.

0

Según la respuesta anterior, se me ocurrió la idea de crear un TypeConverter para acceder a cualquier propiedad estática. Aquí está mi aplicación:

Implementación TypeConverter

using System; 
using System.ComponentModel; 
using System.Reflection; 

namespace EntLibUnity.Extensions 
{ 
    /// <summary> 
    /// Converts an (formatted) string to a reference of a given static member. 
    /// The string uses this format: {member}@{assemblyQualifiedName} 
    /// For example: 
    ///  [email protected], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
    /// </summary> 
    public class StringToStaticInstanceTypeConverter : TypeConverter 
    { 
     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
     { 
      return (typeof(string) == sourceType) || base.CanConvertFrom(context, sourceType); 
     } 

     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
     { 
      string stringValue; 
      if (value == null 
       || (stringValue = value as string) == null 
       || string.IsNullOrEmpty(stringValue) 
       || !stringValue.Contains("@") 
      ) 
      { 
       return null; 
      } 

      var stringParts = stringValue.Split('@'); 
      if (stringParts.Length != 2) 
      { 
       return null; 
      } 
      var staticProperty = stringParts[0]; 
      var assemblyQualifiedName = stringParts[1]; 
      var staticClassType = Type.GetType(assemblyQualifiedName, true); 
      var staticPropertyInfo = staticClassType.GetProperty(staticProperty, 
                   BindingFlags.Public | BindingFlags.Static | 
                   BindingFlags.FlattenHierarchy); 
      var staticValue = staticPropertyInfo.GetValue(null, null) ?? base.ConvertFrom(context, culture, value); 
      return staticValue; 
     } 
    } 
} 

Un ejemplo de uso: dejar suponer la siguiente interfaz y la aplicación concreta:

namespace EntLibUnity.UnitySample 
{ 
    public class VersionManager : IVersionManager 
    { 
     private readonly Version _version; 

     public string Version 
     { 
      get { return _version.ToString(); } 
     } 

     public VersionManager(Version version) 
     { 
      _version = version; 
     } 
    } 
} 

namespace EntLibUnity.Infrastructure 
{ 
    public interface IVersionManager 
    { 
     string Version { get; } 
    } 
} 

Nuestra versión concreta depende de System.Version , entonces configuramos el contenedor para proporcionar este valor. En mi ejemplo usaré el archivo de configuración para este propósito.

<?xml version="1.0" encoding="utf-8" ?> 
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> 
    <!-- Using Design-Time Configuration: http://msdn.microsoft.com/en-us/library/ff660935(v=PandP.20).aspx#format_config --> 
    <!-- The Unity Configuration Schema: http://msdn.microsoft.com/en-us/library/ff660914(v=PandP.20).aspx --> 
    <!-- Specifying Types in the Configuration File http://msdn.microsoft.com/en-us/library/ff660933(v=PandP.20).aspx#_Default_Aliases_and--> 

    <alias alias="StringToStaticInstanceTypeConverter" type="EntLibUnity.Extensions.StringToStaticInstanceTypeConverter, EntLibUnity.Extensions" /> 
    <alias alias="IVersionManager" type="EntLibUnity.Infrastructure.IVersionManager, EntLibUnity.Infrastructure" /> 
    <alias alias="VersionManager" type="EntLibUnity.UnitySample.VersionManager, EntLibUnity.UnitySample" /> 

    <container> 
    <register type="IVersionManager" mapTo="VersionManager"> 
     <constructor> 
     <param name="version"> 
      <value value="[email protected], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" typeConverter="StringToStaticInstanceTypeConverter" /> 
     </param> 
     </constructor> 
    </register> 
    </container> 

</unity> 

Por último, una vez que haya cargado la configuración, puede utilizar la siguiente manera:

var versionManager = container.Resolve<IVersionManager>(); 
Console.WriteLine(versionManager.Version); 

Buena suerte

Cuestiones relacionadas