2010-08-15 13 views
10

Estoy trabajando en una utilidad para SharePoint. Es una aplicación que funciona tanto para SharePoint 2007 como para 2010. Cuando tengo una referencia a la versión 12.0.0.0 de SharePoint.dll, la aplicación funciona para SharePoint 2007, pero no para 2010. Si hago referencia a la versión 14.0.0.0 del dll, entonces la aplicación funciona muy bien para 2010, pero no para 2007.Elija dinámicamente en el tiempo de ejecución qué versión de un .dll usar

Puedo decir fácilmente .dll que necesito usar buscando en el sistema de archivos el siguiente código, comprobando 12 en la ruta (SharePoint 2007) o 14 (SharePoint 2010).

System.IO.File.Exists(
        Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + 
        @"\Microsoft Shared\web server extensions\14\ISAPI\Microsoft.SharePoint.dll")); 

Al desarrollar, hago la referencia en Visual Studio, por lo que se construye ya sea para 2007 o 2010. Quiero ser capaz de liberar la aplicación donde se trabaja en tanto en la versión de SharePoint. Entonces, necesito alguna manera de cargar/usar lo que sea que tenga .dll para el usuario que ejecuta la aplicación.

¿Cómo elijo dinámicamente y cargo un .dll en tiempo de ejecución?

Respuesta

14

reflexión? ¿Inyección de dependencia? ¡Estás haciendo la vida difícil para ti!

Compilar contra Microsoft.SharePoint.dll v12 y que funcionará en 2007.

Implementar en 2010 y que será 'sólo trabajo' (en casi todos los casos) como SharePoint 2010 ya se redirige vinculante por lo que cualquier instalación la referencia a v12 se redirigirá a v14.

No necesita hacer nada de configuración.

Las únicas situaciones en las que necesita para obtener más compleja que esto son

  • Los casos en que algo iba a trabajar en 2007, pero no en 2010 (no puedo pensar en nada a mano).

  • Donde es posible que desee hacer uso de características específicas de 2010.

Si este es el caso, entonces lo que yo personalmente haría es compilar dos veces. Modifique el archivo .csproj para producir 2 versiones ligeramente diferentes, use un parámetro y una compilación condicional (como lo haría con #if DEBUG) para las versiones de código específicas del producto cuando sea necesario (habrá muy pocas de ellas). También puede usar estas condiciones en las referencias en .csproj, p. Ej.

<Reference Include="Microsoft.SharePoint"> 
    <HintPath Condition="'$(SP2010)'!='true'">PathToV12\Microsoft.SharePoint.dll</HintPath> 
    <HintPath Condition="'$(SP2010)'=='true'">PathToV14\Microsoft.SharePoint.dll</HintPath>   
</Reference> 

Desventajas

  • Se termina con 2 versiones de su programa

Ventajas

  • Se termina con 2 versiones de su programa! Muchos de los cambios que podría querer hacer en la versión de 2010 serían en manifet.xml, feature.xml y los demás archivos de configuración: reflexión, inyección de dependencias, etc., aquí no hará nada por usted.
  • Todavía tiene una versión única de código fuente (con compilación condicional menor)
  • El compilador recogerá más errores (por ejemplo, no se puede deducir en tiempo de compilación que esa cosa funky que está haciendo con Reflection para llamar a el nuevo método en v14 funcionará realmente)
+0

+1 para un mejor acercamiento –

+0

Muy informativo en muchos niveles. ¡Aprendí 3 cosas nuevas aquí! ¡Gracias! –

2

Creo que debe tener en cuenta la redirección de enlace de ensamblaje en el marco.

http://msdn.microsoft.com/en-us/library/2fc472t2.aspx

Usted puede utilizar la 'herramienta Configuración de .NET Framework' para configurar la redirección.

+0

Una redirección de enlace es la configuración, que no es dinámica. –

+0

@Kent Boogaart - sí, pero como sabe qué ensamblajes cargar, estos se pueden configurar ¿verdad? – SoftwareGeek

+0

Solo si quiere configurar selectivamente la aplicación para cada máquina a la que está implementando, lo que él declara que no hace. Quiere implementar una vez y hacer que funcione independientemente de la versión de SP instalada. –

3

A modo de AppDomain.AssemblyResolve, se puede comprobar la existencia de la DLL y devolver lo que sea actual:

AppDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e) 
{ 
    if (e.Name == "Microsoft.SharePoint") 
    { 
     // do your check here and return the appropriate Assembly 
     // or maybe just skip an explicit check and instead return either 
     // Assembly.Load("Microsoft.SharePoint, Version=14.0.0.0") or 
     // Assembly.Load("Microsoft.SharePoint, Version=12.0.0.0"), whichever works first 
     // but beware of recursion! 
    } 
}; 

Una redirección de enlace de ensamblado no va a funcionar para usted en este caso, ya que es estática en su archivo de configuración y desea que esto funcione dinámicamente en cualquier máquina con SP2007 o SP2010.

+0

+1 - tuve que lidiar con esto en el pasado y esto es lo que hice. –

+0

No necesita hacer esto - vea mi respuesta. Los redireccionamientos vinculantes ya están implementados en SharePoint 2010 para redirigir v12 a v14, por lo que funcionará de manera 'automática' y dinámica. Ah, y 2007 redirige 2003 (v11) a v12 también. – Ryan

-1

Esto suena como un gran caso para Dependency Injection usando uno de los frameworks DI como Unity o Castle Windsor. Hay otros por ahí, pero ya estoy arriesgando una guerra religiosa simplemente mencionando estos dos. :)

4

Necesita usar la reflexión. Eche un vistazo a Assembly.LoadFile y Assembly.Load.

Si tiene que trabajar con métodos de la clase en que se puede utilizar de esta manera:

 Assembly u = Assembly.LoadFile(path); 
     Type t = u.GetType(class title); 
     if (t != null) 
     { 
      MethodInfo m = t.GetMethod(method); 
      if (m != null) 
      { 
       if (parameters.Length >= 1) 
       { 
        object[] myparam = new object[1]; 
        myparam[0] = ......; 
        return (string)m.Invoke(null, myparam); 
       } 
       else 
       { 
        return (string)m.Invoke(null, null); 
       } 
      } 
     } 
     else 
     { 
      // throw exception. type not found 
     } 
+0

¿Algún motivo para votar a la baja? – Incognito

Cuestiones relacionadas