我有一个包含所有数据库逻辑的类库。我的DAL / BLL。
我有一些Web项目将使用相同的数据库和类,所以我认为将数据层抽象到自己的项目中是一个好主意。
但是,当为某些项目的类添加功能时,我想向某些类添加方法。
例如,我的数据层有Product和SomeItem对象:
// Data Access Layer project
namespace DAL {
public class Product {
//implementation here
}
public class SomeItem {
//implementation here
}
}
在一个项目中,我想添加一个由不同内容项使用的接口,所以我有一个名为:
的类// This is in Web Project
namespace DAL {
public partial class Product : ICustomBehaviour {
#region ICustomBehaviour Implementation
TheSharedMethod();
#endregion
}
}
使用相同的命名空间在单独的项目中创建一个部分类(创建一个依赖项)是个好主意吗?如果这是一个坏主意,我怎样才能使这种类型的功能起作用?
它似乎不想在编译时合并它们,所以我不确定我做错了什么。
答案 0 :(得分:76)
您不能跨项目编写部分类。部分类是一个只编译时间的语法糖 - 整个类型最终都在一个程序集中,即一个项目。
(顺便说一下,你原来的DAL文件必须声明该类是偏的。)
答案 1 :(得分:5)
我无法回答关于组织图层的最佳方式的问题,但我可以尝试回答有关如何最好地模拟部分类的问题。
以下是一些想法:
答案 2 :(得分:4)
部分类必须存在于同一个程序集中。否则,编译器将如何决定将部分类合并到哪里?
答案 3 :(得分:4)
使用Visual Studio 2015及更高版本可以在项目之间拆分部分类:使用shared projects(另请参阅this MSDN blog)。
根据我的情况,我需要以下内容:
以下示例演示了部分类和共享项目如何允许在不同项目上拆分类。
在类库中,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引用类库,不共享项目:
<?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的共享项目。
使用相同的命名空间在单独的项目中创建一个部分类(创建一个依赖项)是一个好主意吗?
经常没有(见其他答案);在某些情况下,如果你知道你在做什么,它可以很方便。
答案 4 :(得分:1)
我认为没有理由不采用这种方案:
两个文件包含存储机制(或其他一些功能)。它们指定继承但不包含业务逻辑:
一个文件包含业务逻辑:
现在创建两个项目:
两个项目都使用相同的业务逻辑。
答案 5 :(得分:0)
我同意Jon Skeet的回答。
我认为无论如何处理这样的问题都不是一个好的选择。有很好的设计模式已经证明了分割你的层/代码层的最佳方法,这只是一点点语法糖,因此微软可以将WinForms / WebForms设计器文件分开,防止人们破坏它们。 / p>
答案 6 :(得分:0)
虽然在谈到pre-linq开发时我同意你的看法,但我也希望能够做到这一点,以便将业务逻辑从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时拆分图层/层的推荐方法。
答案 7 :(得分:0)
不可以。你不能在不同的项目中编写部分类。因为编译器只获得一个项目进行编译,因此只扫描该项目中的类,方法,字段等列表。所以如果你有一些部分的在其他项目中的部分类,编译器无法找到那些。