C# 您是否应该在项目中使用分部类?

C# 您是否应该在项目中使用分部类?,c#,partial-classes,C#,Partial Classes,我有一个包含所有数据库逻辑的类库。我的DAL/BLL 我有几个web项目将使用相同的数据库和类,因此我认为将数据层抽象到自己的项目中是个好主意 然而,当涉及到为某些项目的类添加功能时,我想为某些类添加方法 例如,“我的数据层”包含Product和SomeItem对象: // Data Access Layer project namespace DAL { public class Product { //implementation here } public c

我有一个包含所有数据库逻辑的类库。我的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
  }
}
在单独的项目中使用相同的名称空间编写分部类(创建依赖项)是一个好主意吗?如果这是一个坏主意,我如何才能让这种功能发挥作用?


它似乎不想在编译时合并它们,所以我不确定我做错了什么。

不能跨项目编写分部类。分部类是编译时唯一的一块语法糖——整个类型以单个程序集结束,即一个项目


(顺便说一下,您的原始DAL文件也必须声明该类为分部类。)

分部类必须存在于同一程序集中。否则,编译器将如何决定将分部类合并到何处?

我同意Jon Skeet的答案


无论如何,我认为处理这样的问题不是一个好的选择。现在已经有好的设计模式展示了分割代码层的最佳方法,这只是一点语法糖分,这样Microsoft就可以将WinForms/WebForms designer文件分开,防止人们破坏它们。

虽然我同意你的观点,尼尔,在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时,建议采用什么样的分层方法。

我无法回答您关于组织层的最佳方法的问题,但我可以尝试回答您关于如何最好地模拟部分类的问题

以下是一些想法:

  • 首先想到的是遗产。它不一定总是最好的解决方案,但您可能没有选择,因为您可能需要能够将对象像基类一样对待
  • 作文也是一个不错的选择(也就是说,在另一个类中包装该类)。这使您能够更好地与DAL分离,但实现起来可能会很繁琐
  • <>如果你真的只需要在现有的类上添加一两个方法,你也可以考虑使用一个,但是如果你使用太多,它们会很快创建意大利面代码。
我看不出这个计划不起作用的原因:

两个文件包含存储机制(或某些其他功能)。它们指定继承,但不包含业务逻辑:

  • ProductDataAccess.cs
  • ProductWeb.cs
一个文件包含业务逻辑:

  • ProductBusinessLogic.cs
现在创建两个项目:

  • WebProject包含ProductWeb.cs和ProductBusinessLogic.cs
  • DataProject包含ProductDataAccess.cs和ProductBusinessLogic.cs

两个项目都使用相同的业务逻辑。

否。您不能在不同的项目中编写分部类。因为编译器每次只获取一个项目进行编译,因此只扫描该项目中的类、方法、字段等列表。因此,如果您在其他项目中有分部类的某些部分,编译器找不到这些类。

使用Visual Studio 2015及更高版本可以跨项目拆分部分类:使用(另请参见)

就我的情况而言,我要求如下:

  • 一个类库,它定义了一些被多个客户端应用程序用作接口的类
  • 客户端应用程序
  • 在数据库中创建表的安装应用程序。
    由于安装程序的限制,此设置必须是独立的。它不能引用.NET framework之外的任何程序集。安装程序应该在表中插入一些枚举常量,因此理想情况下应该引用类库。
    安装程序可以导入共享项目
  • 因为共享项目类似于复制粘贴代码,所以我希望尽可能少地移动到共享项目中
下面的示例演示了分部类和共享项目如何允许在不同的项目上拆分类

在类库中,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; }
    }
}
类库是一个普通的VisualStudio类库。它导入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>
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>
常规客户端csproj引用类库和而不是共享项目:

namespace SharedPartialCodeTryout.DataTypes
{
    public partial class Address
    {
        public enum Direction
        {
            NORTH,
            EAST,
            SOUTH,
            WEST
        }
    }
}
<?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>
<?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>

Exe
{7383254d-bd80-4552-81f8-a723ce384198}
SharedPartialCodeRyout.DataTypes
DbSetup仅使用枚举:

DbSetup.csproj不引用类库;它只导入SharedProject:

namespace SharedPartialCodeTryout.DataTypes
{
    public partial class Address
    {
        public enum Direction
        {
            NORTH,
            EAST,
            SOUTH,
            WEST
        }
    }
}
<?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>
<?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>

Exe

那么,我可以在另一个项目的类中添加“接口”功能吗?@Kent:晚上8点不行,不行:)@Atomiton:你不能从其他项目中更改现有类,不行。你可以从现有类派生并实现接口。但这也有一些缺点——最明显的是,您必须确保始终创建新类型的实例,而不是基本类型的实例。@Sabuncu:是的,这是可能的,尽管很少有用。我认为我不希望它成为默认行为,因为这表明可能还有另一个部件需要寻找。@Amir:它并不是真正跨程序集的。它只是包括