5 Stimmen

Registrieren einer Instanz in config mit Unity

Wie man eine Instanz in der Konfigurationsdatei registriert

Ich habe diesen Code:

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

Und versuchen, das Äquivalent in einer Konfigurationsdatei zu haben

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

Meine CacheMng-Klasse hat diesen Konstruktor

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

Ich erhalte folgende Fehlermeldung

Der Typname oder der Alias System.Web.Caching konnte nicht aufgelöst werden

3voto

Ronald Wildenberg Punkte 30961

Der Grund für die Fehlermeldung, die Sie sehen, ist, dass die type Parameter erfordert einen Typnamen und keinen Namensraumnamen. System.Web.Caching ist ein Namespace und kein Typ.

Die einzige Möglichkeit, dies zu tun, besteht darin, einen eigenen Typkonverter zu schreiben und die value Element, etwa so:

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

Der Typkonverter sieht in etwa so aus (in seiner einfachsten Form):

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

Sie könnten dies allgemeiner anwenden, indem Sie einen Wert für die Unity value Element (zum Beispiel: System.Web.HttpRuntime.Cache ) und lassen Sie den Typkonverter auf der Grundlage dieses Wertes das richtige Objekt zurückgeben.

0voto

hmadrigal Punkte 990

Basierend auf der vorherigen Antwort kam ich auf die Idee, einen TypeConverter zu erstellen, um auf jede statische Eigenschaft zuzugreifen. Hier ist meine Implementierung:

TypeConverter-Implementierung

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:
    ///     Version@System.Environment, 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;
        }
    }
}

Ein Beispiel für die Verwendung: Nehmen wir die folgende Schnittstelle und konkrete Implementierung an:

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

Unsere konkrete Version hängt von System.Version ab, also konfigurieren wir den Container so, dass er diesen Wert liefert. In meinem Beispiel werde ich die Konfigurationsdatei für diesen Zweck verwenden.

<?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="Version@System.Environment, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" typeConverter="StringToStaticInstanceTypeConverter" />
        </param>
      </constructor>
    </register>
  </container>

</unity>

Sobald Sie die Konfiguration geladen haben, können Sie sie wie folgt verwenden:

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

Viel Glück!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X