すべてのデータベースロジックを含むクラスライブラリがあります。私のDAL/BLL。
同じデータベースとクラスを使用するWebプロジェクトがいくつかあるので、データレイヤーを独自のプロジェクトに抽象化することをお勧めします。
ただし、特定のプロジェクトのクラスに機能を追加することになると、特定のクラスにメソッドを追加する必要があります。
たとえば、私のデータレイヤーにはProductオブジェクトとSomeItemオブジェクトがあります。
// Data Access Layer project
namespace DAL {
public class Product {
//implementation here
}
public class SomeItem {
//implementation here
}
}
1つのプロジェクトで、さまざまなコンテンツアイテムで使用されるインターフェイスを追加したいので、次のクラスを呼び出します。
// This is in Web Project
namespace DAL {
public partial class Product : ICustomBehaviour {
#region ICustomBehaviour Implementation
TheSharedMethod();
#endregion
}
}
same名前空間を使用して、部分クラスを別のプロジェクトに作成する(依存関係を作成する)ことは良い考えですか?このタイプの機能を機能させるにはどうすればよいですか?
コンパイル時にそれらをマージしたくはないようですので、私は何が間違っているのかわかりません。
プロジェクト間で部分クラスを作成することはできません。部分クラスは、コンパイル時のみの構文糖衣です。タイプ全体が単一のアセンブリ、つまり1つのプロジェクトになります。
(ちなみに、元のDALファイルでは、クラスも部分的であると宣言する必要があります。)
レイヤーを整理する最良の方法についての質問にはお答えできませんが、部分クラスをエミュレートするための最良の方法についての質問にお答えすることはできます。
ここにいくつかの考えがあります:
Visual Studio 2015以降を使用すると、プロジェクト間で部分クラスを分割できます: shared projects ( こちらのMSDNブログもご覧ください )。
私の状況では、次のものが必要でした。
次の例は、部分クラスと共有プロジェクトがクラスを異なるプロジェクトに分割する方法を示しています。
クラスライブラリの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; }
}
}
クラスライブラリは、通常のVisual Studioクラスライブラリです。 SharedProjectをインポートしますが、その.csprojには何も特別なものは含まれていません。
<?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
はSharedProjectに実装されています。
namespace SharedPartialCodeTryout.DataTypes
{
public partial class Address
{
public enum Direction
{
NORTH,
EAST,
SOUTH,
WEST
}
}
}
SharedProject.shprojは次のとおりです。
<?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>
そして、その.projitemsは次のとおりです。
<?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>
通常のクライアントはAddress
を含み、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}");
}
}
}
通常のクライアントcsprojはクラスライブラリを参照し、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は列挙型のみを使用します。
DbSetup.csprojはクラスライブラリを参照しません。 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>
結論として:
部分クラスをプロジェクト間で分割できますか?
はい、Visual Studioの共有プロジェクトを使用します。
同じ名前空間を使用して別のプロジェクトで(依存関係を作成して)部分クラスを作成することは良い考えですか?
多くの場合、そうではありません(他の回答を参照)。状況によっては、自分が何をしているのかわかっている場合に便利です。
部分クラスは同じアセンブリに存在する必要があります。それ以外の場合、コンパイラは部分クラスをどこにマージするかをどのように決定しますか?
このスキームが機能しない理由はわかりません。
2つのファイルには、ストレージメカニズム(またはその他の機能)が含まれています。継承を指定しますが、ビジネスロジックは含まれません。
1つのファイルにはビジネスロジックが含まれています。
次に、2つのプロジェクトを作成します。
どちらのプロジェクトも同じビジネスロジックを使用します。
いいえ。異なるプロジェクトに部分クラスを書き込むことはできません。一度にコンパイラがコンパイルする単一のプロジェクトを取得し、そのプロジェクトのクラス、メソッド、フィールドなどのリストのみをスキャンするためです。したがって、部分クラスの一部が他のプロジェクト、コンパイラはそれらを見つけることができません。
Linqより前の開発に関してはNeilに同意しますが、Linq2SQLデザイナーによって生成された部分クラスからビジネスロジックを分割するためにこれを実行できたらいいのにと思います。例えば:
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)
残念ながら、これを行うことはできません... LINQを使用するときにレイヤー/層を分割する推奨方法を知りたいのですが。
ジョン・スキートの答えに同意します。
とにかく、このような問題に取り組むのは良い選択ではないと思います。コードの層/層を分割する最良の方法を示す優れた設計パターンがすでにあります。これは、MicrosoftがWinForms/WebFormsデザイナーファイルを分離して、ユーザーがそれらを壊すのを防ぐことができるようにするための、単なる構文上の砂糖です。