11

yo estaba tratando de utilizar la Unidad 2.0 beta 2 para Silverlight en mi proyecto de Windows Phone 7 y seguí recibiendo este accidente:inyección de dependencias para Windows Phone 7

Microsoft.Practices.Unity.Silverlight.dll Microsoft.Practices .ObjectBuilder2.DynamicMethodConstructorStrategy.DynamicMethodConstructorStrategy() + 0x1f bytes

 
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.DynamicMethodConstructorStrategy() + 0x1f bytes mscorlib.dll!System.Reflection.RuntimeConstructorInfo.InternalInvoke(System.Reflection.RuntimeConstructorInfo rtci = {System.Reflection.RuntimeConstructorInfo}, System.Reflection.BindingFlags invokeAttr = Default, System.Reflection.Binder binder = null, object parameters = {object[0]}, System.Globalization.CultureInfo culture = null, bool isBinderDefault = false, System.Reflection.Assembly caller = null, bool verifyAccess = true, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) 
mscorlib.dll!System.Reflection.RuntimeConstructorInfo.InternalInvoke(object obj = null, System.Reflection.BindingFlags invokeAttr = Default, System.Reflection.Binder binder = null, object[] parameters = {object[0]}, System.Globalization.CultureInfo culture = null, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) + 0x103 bytes 
mscorlib.dll!System.Activator.InternalCreateInstance(System.Type type = {Name = "DynamicMethodConstructorStrategy" FullName = "Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy"}, bool nonPublic = false, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) + 0xf0 bytes mscorlib.dll!System.Activator.CreateInstance() + 0xc bytes 
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.ObjectBuilder2.StagedStrategyChain.AddNew(Microsoft.Practices.Unity.ObjectBuilder.UnityBuildStage stage = Creation) + 0x1d bytes  
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityDefaultStrategiesExtension.Initialize() + 0x6c bytes 
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityContainerExtension.InitializeExtension(Microsoft.Practices.Unity.ExtensionContext context = {Microsoft.Practices.Unity.UnityContainer.ExtensionContextImpl}) + 0x31 bytes 
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityContainer.AddExtension(Microsoft.Practices.Unity.UnityContainerExtension extension = {Microsoft.Practices.Unity.UnityDefaultStrategiesExtension}) + 0x1a bytes 
Microsoft.Practices.Unity.Silverlight.dll!Microsoft.Practices.Unity.UnityContainer.UnityContainer() + 0xf bytes 

pensando que podía resolverlo he intentado un par de cosas, pero en vano.

Resulta que este es un problema bastante fundamental y mi suposición de que Windows Phone 7 es Silverlight 3 + Algunas otras cosas están mal. Este page describe las diferencias entre móvil Silverlight y Silverlight 3.

De particular interés es la siguiente:

El espacio de nombres System.Reflection.Emit no está soportada en Silverlight para Windows Phone.

Esta es precisamente la razón por la Unidad está fallando en el teléfono, DynamicMethodConstructorStrategySystem.Reflection.Emit clase utiliza extensamente ...

Así que la pregunta es, ¿qué alternativa a la Unidad está ahí para Windows Phone 7?

+1

Informe que como un error a la unidad del equipo. Silverlight y Windows Phone deberían tener la misma API (excepto Windows Phone tiene algunas cosas adicionales). – CVertex

+1

Esto no es realmente un error. Existen enormes diferencias entre Silverlight3 y Windows Phone Silverlight. El equipo de la unidad es consciente de ello: http://unity.codeplex.com/Thread/View.aspx?ThreadId=207143 Tal vez lanzan una versión con soporte telefónico. –

Respuesta

5

Funq ha estado en desarrollo durante más de un año y ahora tiene una versión 1.0. Está diseñado para ser rápido y funcionar bajo Compact Framework y Windows Phone 7. Otra gran ventaja es que el autor ha hecho un excelente screencast series explicando su proceso de desarrollo usando TDD que es muy informativo.

Como un lado, las pruebas de rendimiento más recientes que puedo encontrar son from March 2009 que muestran cómo superar los pantalones de Unity, Autofac, Ninject y StructureMap. Estoy intentando localizar pruebas más recientes y actualizaré esta publicación si lo hago.

+0

Funq 1.0.0 no es compatible con Windows Phone 7.1. Ninject 3.0.1 funciona bien. –

2

Si no puede encontrar un contenedor IOC que funcione en Windows Phone 7 (y no me sorprendería que no pueda), le sugiero que vaya con a different DI strategy.

+0

Gracias por eso. El artículo refleja muchos de los pensamientos que tuve sobre el uso de un contenedor DI. Desafortunadamente, necesito una solución con un nivel ligeramente más alto de automaticidad para crear aplicaciones muy ligeramente acopladas (algunas partes de las cuales se generan). Estoy un poco de acuerdo, que con un uso intensivo de marcos de DI 'System.Reflection' podría estar fundamentalmente repleto de WP7. –

+0

Gracias, este es un gran artículo. – nlawalker

+0

Enlace roto. ¡Me gustaría leerlo sin embargo! – MEMark

7

Por lo tanto, en el espíritu de responder mis propias preguntas, he creado un contenedor DI simple (usando Activator.CreateInstance para crear instancias de cosas). Todo lo que hace es el tipo de soporte de registros y registros de instancias.

Parece que está haciendo el trabajo. Te preocupes por el rendimiento más tarde.

public class DuplicateRegistrationException : Exception { 
    public DuplicateRegistrationException() { } 
    public DuplicateRegistrationException(string message) : base(message) { } 
    public DuplicateRegistrationException(string message, Exception inner) : base(message, inner) { } 
} 

public interface IDIContainer { 
    void Register<TIntf, TClass>() where TIntf: class where TClass : TIntf; 
    TIntf Resolve<TIntf>() where TIntf : class; 
    void RegisterInstance<TIntf>(TIntf instance); 
} 

public class DIContainer : IDIContainer{ 

    Dictionary<Type, Type> m_TypeRegistrations; 
    Dictionary<Type, object> m_InstanceRegistrations; 

    public DIContainer() { 
     m_TypeRegistrations = new Dictionary<Type, Type>(); 
     m_InstanceRegistrations = new Dictionary<Type, object>(); 
    } 

    #region IDIContainer Members 

    public void Register<TIntf, TClass>() 
     where TIntf : class 
     where TClass : TIntf { 
      if(DoesRegistrationExist<TIntf>()) 
       throw new DuplicateRegistrationException("Can only contain one registration per type"); 
      m_TypeRegistrations.Add(typeof(TIntf), typeof(TClass)); 
    } 

    public TIntf Resolve<TIntf>() where TIntf : class { 
     return Resolve(typeof(TIntf)) as TIntf; 
    } 

    private object Resolve(Type type) { 
     if(!m_TypeRegistrations.ContainsKey(type)) { 
      if(!m_InstanceRegistrations.ContainsKey(type)) 
       throw new NotSupportedException("Cannot find registration for type " + type.FullName + "."); 
      else 
       return m_InstanceRegistrations[type]; 
     } else { 
      var createdType = m_TypeRegistrations[type]; 

      ConstructorInfo[] constructors = createdType.GetConstructors(); 
      ConstructorInfo mostSpecificConstructor = null; 
      foreach(var c in constructors) { 
       if(mostSpecificConstructor == null || mostSpecificConstructor.GetParameters().Length < c.GetParameters().Length) { 
        mostSpecificConstructor = c; 
       } 
      } 

      List<object> constructorParameters = new List<object>(); 
      foreach(var a in mostSpecificConstructor.GetParameters()) { 
       constructorParameters.Add(Resolve(a.ParameterType)); 
      } 

      return Activator.CreateInstance(createdType, constructorParameters.ToArray()); 
     } 
    } 

    private bool DoesRegistrationExist<T>() { 
     return m_InstanceRegistrations.ContainsKey(typeof(T)) || m_TypeRegistrations.ContainsKey(typeof(T)); 
    } 

    public void RegisterInstance<TIntf>(TIntf instance) { 
     if(DoesRegistrationExist<TIntf>()) { 
      throw new DuplicateRegistrationException("Can only contain one registration per type"); 
     } 
     m_InstanceRegistrations.Add(typeof(TIntf), instance); 
    } 


    #endregion 
+0

Activator.CreateInstance consume muchos recursos. Recomendaría usar Funq como método alternativo. Mira la primera serie de castings de pantalla de "http://blogs.clariusconsulting.net/kzu/funq-screencast-series-on-how-to-building-a-di-container-using-tdd/" y verás . –

+0

Esta publicación se realizó aproximadamente un mes después de que salió WP7 SDK, en cuyo momento no había contenedores aceptables WP7 DI. Habiendo dicho eso, no sabía que compilar expresiones para lambdas está permitido en WP7 sandbox. –

2

Acabo de comenzar a armar un proyecto de Windows Phone 7 Extension Tools en codeplex. La versión actual marcada admite IoC con DI implícita junto con el Localizador de servicios comunes para permitir la abstracción completa de su código y el contenedor que utilizan.

Compruebe hacia fuera más en: http://wp7.codeplex.com

Cheers, Simon Hart

1

El OpenNETCF.IoC framework funciona en el escritorio de Windows, Mono, Windows Mobile, Windows Phone 7 y MonoTouch. Soy un fanático de la reutilización de código.

Está modelado según el SCSF/CAB (en el modelo de objetos, no en el rendimiento defectuoso), por lo que muchos de estos tutoriales son válidos y puede aprovechar el conocimiento existente y los recursos del código.

1

A pesar de Marcos dice Seeman "el mundo no necesita otro contenedor" en su libro excelente "inyección de dependencia en .NET", decidí aplicar mi propio contenedor DI para WP7 que proporciona la mayor DI características:

  • composición de objetos
  • gestión de vida
  • intercepción que permite t o aspecto se aproxima a la programación orientada

El contenedor es la parte de PhoneCore marco, que se puede encontrar aquí: http://phonecore.codeplex.com