una tipo proyecto parciales parcial objetos modificador metodos falta ejemplos ejemplo definicion declaración clases clase agregar c# partial-classes

c# - tipo - ¿Deberías usar una clase parcial en todos los proyectos?



partial class c# ejemplo (8)

Estoy de acuerdo con la respuesta de Jon Skeet.

No creo que sea una buena opción abordar un tema como este de todos modos. Ya hay buenos patrones de diseño que demuestran la mejor manera de dividir los niveles / capas de código, y esto es solo un poco de azúcar sintáctico para que Microsoft pueda separar los archivos de diseñador de WinForms / WebForms e impedir que las personas los rompan.

Tengo una biblioteca de clases con toda la lógica de mi base de datos. Mi DAL / BLL.

Tengo algunos proyectos web que usarán la misma base de datos y clases, así que pensé que era una buena idea abstraer la capa de datos en su propio proyecto.

Sin embargo, cuando se trata de agregar funcionalidad a clases para ciertos proyectos, quiero agregar métodos a ciertas clases.

Por ejemplo, mi capa de datos tiene objetos Product y SomeItem:

// Data Access Layer project namespace DAL { public class Product { //implementation here } public class SomeItem { //implementation here } }

En un proyecto, quiero agregar una interfaz que es utilizada por diferentes elementos de contenido, así que tengo una clase llamada:

// This is in Web Project namespace DAL { public partial class Product : ICustomBehaviour { #region ICustomBehaviour Implementation TheSharedMethod(); #endregion } }

¿Es una buena idea escribir una clase parcial en un proyecto separado (creando una dependencia) usando el mismo espacio de nombres? Si es una mala idea, ¿cómo puedo hacer que funcione este tipo de funcionalidad?

No parece querer combinarlos en tiempo de compilación, así que no estoy seguro de lo que estoy haciendo mal.


Las clases parciales deben existir en el mismo ensamblaje. De lo contrario, ¿cómo decidiría el compilador dónde fusionar las clases parciales?


No puedes escribir una clase parcial en todos los proyectos. Una clase parcial es una pieza de azúcar sintáctica en tiempo de compilación, todo el tipo termina en un único ensamblaje, es decir, un proyecto.

(Por cierto, su archivo DAL original también tendría que declarar la clase como parcial).


No puedo responder su pregunta sobre la mejor manera de organizar sus capas, pero puedo intentar responder su pregunta sobre la mejor forma de emular las clases parciales.

Aquí hay algunos pensamientos:

  • Lo primero que viene a la mente es la herencia. No siempre es la mejor solución, pero es posible que no tenga otra opción, ya que es posible que necesite que sus objetos puedan ser tratados como la clase base.
  • La composición también es una buena opción (es decir, envolver la clase en otra clase). Esto te ofrece un desacoplamiento un poco más agradable de tu DAL, pero puede ser tedioso de implementar.
  • Si realmente necesita agregar un método o dos a una clase existente, también podría considerar usar un método de extensión , pero estos pueden crear código de espagueti rápidamente si los usa demasiado.

Si bien estoy de acuerdo con Neil en lo que respecta al desarrollo pre-linq, también me gustaría poder hacerlo para dividir la lógica empresarial de las clases parciales generadas por el diseñador Linq2SQL. Por ejemplo:

Northind.DAL (prj) -NorthindDataContext (EntityNamespace set to "Northwind.BLL") --Product() (Entity, partial class auto-generated) --Category() (Entity, partial class auto-generated) --Supplier() (Entity, partial class auto-generated) Northind.BLL (prj) -Product() : IMyCustomEnityInterface, BaseEntity (override OnValidate(), etc) -Category() : IMyCustomEnityInterface, BaseEntity (override OnValidate(), etc) -Supplier() : IMyCustomEnityInterface, BaseEntity (override OnValidate(), etc)

Lamentablemente, no podemos hacer esto ... en realidad, me encantaría saber cuál es la forma recomendada de dividir capas / niveles al usar LINQ.


No veo ninguna razón por la cual este esquema no funcionaría:

Dos archivos contienen mecanismos de almacenamiento (u otra característica). Especifican la herencia pero no contienen lógica comercial:

  • ProductDataAccess.cs
  • ProductWeb.cs

Un archivo contiene la lógica de negocios:

  • ProductBusinessLogic.cs

Ahora crea dos proyectos:

  • WebProject contiene ProductWeb.cs y ProductBusinessLogic.cs.
  • DataProject contiene ProductDataAccess.cs y ProductBusinessLogic.cs

Ambos proyectos utilizan la misma lógica comercial.


No. No puedes escribir clases parciales en diferentes proyectos. Debido a que en un momento el compilador obtiene un solo proyecto para la compilación y escanea la lista de clases, métodos, campos, etc. en ese proyecto solamente. Así que si tienes algunas partes de la clase parcial en otros proyectos, el compilador no puede encontrarlos.


Con Visual Studio 2015 y versiones posteriores , es posible dividir las clases parciales en todos los proyectos: utilizar proyectos compartidos (consulte también este blog de MSDN ).

Para mi situación requirió lo siguiente:

  • Una biblioteca de clases que define algunas clases utilizadas como interfaz por varias aplicaciones cliente.
  • La aplicación del cliente.
  • Una aplicación de configuración que crea tablas en la base de datos.
    Debido a las limitaciones del instalador, esta configuración debe ser independiente. No puede hacer referencia a ningún ensamblaje más allá del marco .NET. La configuración debe insertar algunas constantes enum en las tablas, por lo que idealmente debería hacer referencia a la biblioteca de clases.
    La configuración puede importar un proyecto compartido.
  • Como el proyecto compartido es similar al código de copiado, quiero moverme lo menos posible en el proyecto compartido.

El siguiente ejemplo muestra cómo las clases parciales y los proyectos compartidos permiten dividir clases en diferentes proyectos.

En Class Library, Address.cs:

namespace SharedPartialCodeTryout.DataTypes { public partial class Address { public Address(string name, int number, Direction dir) { this.Name = name; this.Number = number; this.Dir = dir; } public string Name { get; } public int Number { get; } public Direction Dir { get; } } }

Class Library es una biblioteca de clases de Visual Studio normal. Importa el SharedProject, más allá de eso, su .csproj no contiene nada especial:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props" Condition="Exists(''$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props'')" /> <PropertyGroup> <!-- standard Visual Studio stuff removed --> <OutputType>Library</OutputType> <!-- standard Visual Studio stuff removed --> </PropertyGroup> <!-- standard Visual Studio stuff removed --> <ItemGroup> <Reference Include="System" /> </ItemGroup> <ItemGroup> <Compile Include="Address.cs" /> <Compile Include="Properties/AssemblyInfo.cs" /> </ItemGroup> <Import Project="../SharedProject/SharedProject.projitems" Label="Shared" /> <Import Project="$(MSBuildToolsPath)/Microsoft.CSharp.targets" /> </Project>

Address.Direction se implementa en SharedProject:

namespace SharedPartialCodeTryout.DataTypes { public partial class Address { public enum Direction { NORTH, EAST, SOUTH, WEST } } }

SharedProject.shproj es:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup Label="Globals"> <ProjectGuid>33b08987-4e14-48cb-ac3a-dacbb7814b0f</ProjectGuid> <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion> </PropertyGroup> <Import Project="$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props" Condition="Exists(''$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props'')" /> <Import Project="$(MSBuildExtensionsPath32)/Microsoft/VisualStudio/v$(VisualStudioVersion)/CodeSharing/Microsoft.CodeSharing.Common.Default.props" /> <Import Project="$(MSBuildExtensionsPath32)/Microsoft/VisualStudio/v$(VisualStudioVersion)/CodeSharing/Microsoft.CodeSharing.Common.props" /> <PropertyGroup /> <Import Project="SharedProject.projitems" Label="Shared" /> <Import Project="$(MSBuildExtensionsPath32)/Microsoft/VisualStudio/v$(VisualStudioVersion)/CodeSharing/Microsoft.CodeSharing.CSharp.targets" /> </Project>

Y sus .projitems es:

<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> <HasSharedItems>true</HasSharedItems> <SharedGUID>33b08987-4e14-48cb-ac3a-dacbb7814b0f</SharedGUID> </PropertyGroup> <PropertyGroup Label="Configuration"> <Import_RootNamespace>SharedProject</Import_RootNamespace> </PropertyGroup> <ItemGroup> <Compile Include="$(MSBuildThisFileDirectory)Address.Direction.cs" /> </ItemGroup> </Project>

El cliente habitual usa la Address incluida la Address :

using SharedPartialCodeTryout.DataTypes; using System; namespace SharedPartialCodeTryout.Client { class Program { static void Main(string[] args) { // Create an Address Address op = new Address("Kasper", 5297879, Address.Direction.NORTH); // Use it Console.WriteLine($"Addr: ({op.Name}, {op.Number}, {op.Dir}"); } } }

El cliente habitual csproj hace referencia a la Biblioteca de clases y no a SharedProject:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props" Condition="Exists(''$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props'')" /> <PropertyGroup> <!-- Removed standard Visual Studio Exe project stuff --> <OutputType>Exe</OutputType> <!-- Removed standard Visual Studio Exe project stuff --> </PropertyGroup> <!-- Removed standard Visual Studio Exe project stuff --> <ItemGroup> <Reference Include="System" /> </ItemGroup> <ItemGroup> <Compile Include="Program.cs" /> <Compile Include="Properties/AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> <None Include="App.config" /> </ItemGroup> <ItemGroup> <ProjectReference Include="../SharedPartialCodeTryout.DataTypes/SharedPartialCodeTryout.DataTypes.csproj"> <Project>{7383254d-bd80-4552-81f8-a723ce384198}</Project> <Name>SharedPartialCodeTryout.DataTypes</Name> </ProjectReference> </ItemGroup> <Import Project="$(MSBuildToolsPath)/Microsoft.CSharp.targets" /> </Project>

DbSetup usa solo las enumeraciones:

DbSetup.csproj no hace referencia a Class Library; solo importa SharedProject:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props" Condition="Exists(''$(MSBuildExtensionsPath)/$(MSBuildToolsVersion)/Microsoft.Common.props'')" /> <PropertyGroup> <!-- Removed standard Visual Studio Exe project stuff --> <OutputType>Exe</OutputType> <!-- Removed standard Visual Studio Exe project stuff --> <?PropertyGroup> <!-- Removed standard Visual Studio Exe project stuff --> <ItemGroup> <Reference Include="System" /> <Reference Include="Microsoft.CSharp" /> </ItemGroup> <ItemGroup> <Compile Include="Program.cs" /> <Compile Include="Properties/AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> <None Include="App.config" /> </ItemGroup> <Import Project="../SharedProject/SharedProject.projitems" Label="Shared" /> <Import Project="$(MSBuildToolsPath)/Microsoft.CSharp.targets" /> </Project>

Para concluir:

¿Puedes dividir una clase parcial en todos los proyectos?

Sí, use los proyectos compartidos de Visual Studio.

¿Es una buena idea escribir una clase parcial en un proyecto separado (creando una dependencia) usando el mismo espacio de nombres?

A menudo no (ver las otras respuestas); en algunas situaciones, y si sabe lo que está haciendo, puede ser útil.