J'ai une bibliothèque de classe avec toute ma logique de base de données. Mon DAL/BLL.
J'ai quelques projets Web qui utiliseront la même base de données et les mêmes classes, j'ai donc pensé que c'était une bonne idée de résumer la couche de données dans son propre projet.
Cependant, lorsqu'il s'agit d'ajouter des fonctionnalités aux classes de certains projets, je souhaite ajouter des méthodes à certaines classes.
Par exemple, ma couche de données contient les objets Product et SomeItem:
// Data Access Layer project
namespace DAL {
public class Product {
//implementation here
}
public class SomeItem {
//implementation here
}
}
Dans un projet, je souhaite ajouter une interface utilisée par différents éléments de contenu. J'ai donc une classe appelée:
// This is in Web Project
namespace DAL {
public partial class Product : ICustomBehaviour {
#region ICustomBehaviour Implementation
TheSharedMethod();
#endregion
}
}
Est-ce une bonne idée d'écrire une classe partielle dans un projet séparé (en créant une dépendance) en utilisant l'espace de noms same ? Si c'est une mauvaise idée, comment puis-je utiliser ce type de fonctionnalité?
Il ne semble pas vouloir les fusionner au moment de la compilation, alors je ne suis pas sûr de ce que je fais mal.
Vous ne pouvez pas écrire une classe partielle sur plusieurs projets. Une classe partielle est un morceau de sucre syntaxique réservé à la compilation. Tout le type se termine en un seul assemblage, c’est-à-dire un projet.
(Au fait, votre fichier DAL d'origine devrait également déclarer la classe partielle).)
Je ne peux pas répondre à votre question sur la meilleure façon d'organiser vos couches, mais je peux essayer de répondre à votre question sur la meilleure façon d'imiter des classes partielles.
Voici quelques réflexions:
Les classes partielles doivent exister dans la même assemblée. Sinon, comment le compilateur déciderait-il où fusionner les classes partielles?
Avec Visual Studio 2015 et les versions ultérieures il est possible de scinder des classes partielles entre projets: utilisez projets partagés (voir aussi ce blog MSDN ).
Pour ma situation j'avais besoin de ce qui suit:
L'exemple suivant montre comment des classes partielles et des projets partagés autorisent le fractionnement de classes sur différents projets.
Dans la bibliothèque de classes, 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; }
}
}
La bibliothèque de classes est une bibliothèque de classes Visual Studio normale. Il importe le SharedProject, au-delà de son .csproj ne contient rien de spécial:
<?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
est implémenté dans le SharedProject:
namespace SharedPartialCodeTryout.DataTypes
{
public partial class Address
{
public enum Direction
{
NORTH,
EAST,
SOUTH,
WEST
}
}
}
SharedProject.shproj est:
<?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>
Et son .projitems est:
<?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>
Le client standard utilise Address
dont Address.Direction
:
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}");
}
}
}
Le client standard csproj fait référence à la bibliothèque de classes et not 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 utilise uniquement les enums:
Le fichier DbSetup.csproj ne fait pas référence à la bibliothèque de classes; il importe uniquement 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>
De conclure:
Pouvez-vous diviser une classe partielle entre plusieurs projets?
Oui, utilisez les projets partagés de Visual Studio.
Est-ce une bonne idée d'écrire une classe partielle dans un projet séparé (créant une dépendance) en utilisant le même espace de noms?
Souvent non (voir les autres réponses); dans certaines situations et si vous savez ce que vous faites, cela peut être pratique.
Je ne vois aucune raison pour que ce schéma ne fonctionne pas:
Deux fichiers contiennent des mécanismes de stockage (ou une autre fonctionnalité). Ils spécifient l'héritage mais ne contiennent aucune logique métier:
Un fichier contient la logique métier:
Maintenant, créez deux projets:
Les deux projets utilisent la même logique métier.
Vous ne pouvez pas écrire de classes partielles dans différents projets.Parce que le compilateur obtient un seul projet pour la compilation, il scanne la liste des classes, méthodes, champs, etc. de ce projet uniquement. autres projets, le compilateur ne peut pas trouver ceux-ci.
Bien que je sois d’accord avec vous pour ce qui est du développement pré-linq, Neil, je souhaiterais également pouvoir le faire afin de séparer la logique de gestion des classes partielles générées par le concepteur Linq2SQL. Par exemple:
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)
Malheureusement, nous ne pouvons pas faire cela. En fait, j'aimerais savoir quelle est la méthode recommandée pour diviser les couches/niveaux en utilisant LINQ.
Je suis d'accord avec la réponse de Jon Skeet.
Je ne pense pas que ce serait un bon choix d’aborder une question comme celle-là de toute façon. Il existe déjà de bons modèles de conception qui démontrent le meilleur moyen de scinder vos niveaux/couches de code. Il ne s'agit que d'un simple sucre syntaxique permettant à Microsoft de séparer les fichiers du concepteur WinForms/WebForms et d'empêcher les utilisateurs de les décomposer.