C# 您应该跨项目使用分部类吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/309939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should you use a partial class across projects?
提问by Armstrongest
I have a class library with all my database logic. My DAL/BLL.
我有一个包含所有数据库逻辑的类库。我的 DAL/BLL。
I have a few web projects which will use the same database and classes, so I thought it was a good idea to abstract the data layer into its own project.
我有几个 web 项目将使用相同的数据库和类,所以我认为将数据层抽象到自己的项目中是个好主意。
However, when it comes to adding functionality to classes for certain projects I want to add methods to certain classes.
但是,当涉及为某些项目的类添加功能时,我想向某些类添加方法。
For example, my data layer has Product and SomeItem objects:
例如,我的数据层有 Product 和 SomeItem 对象:
// Data Access Layer project
namespace DAL {
public class Product {
//implementation here
}
public class SomeItem {
//implementation here
}
}
In one project I want to add an interface that is used by different content items, so I have a class called:
在一个项目中,我想添加一个由不同内容项使用的接口,因此我有一个名为:
// This is in Web Project
namespace DAL {
public partial class Product : ICustomBehaviour {
#region ICustomBehaviour Implementation
TheSharedMethod();
#endregion
}
}
Is it a good idea to write a partial class in a separate project (creating a dependency) using the samenamespace? If it's a bad idea, how can I get this type of functionality to work?
使用相同的命名空间在单独的项目(创建依赖项)中编写分部类是个好主意吗?如果这是一个坏主意,我怎样才能让这种类型的功能发挥作用?
It doesn't seem to want to merge them at compile time, so I'm not sure what I'm doing wrong.
它似乎不想在编译时合并它们,所以我不确定我做错了什么。
采纳答案by Jon Skeet
You can't write a partial class across projects. A partial class is a compile-time-only piece of syntactic sugar - the whole type ends up in a single assembly, i.e. one project.
您不能跨项目编写部分类。分部类是仅编译时语法糖的一部分 - 整个类型以单个程序集结束,即一个项目。
(Your original DAL file would have to declare the class to be partial as well, by the way.)
(顺便说一下,您的原始 DAL 文件也必须将类声明为部分类。)
回答by Kent Boogaart
Partial classes have to exist in the same assembly. Otherwise, how would the compiler decide where to merge the partial classes to?
分部类必须存在于同一个程序集中。否则,编译器将如何决定将部分类合并到哪里?
回答by Neil Barnwell
I agree with Jon Skeet's answer.
我同意 Jon Skeet 的回答。
I don't think it would be a good choice to approach an issue like this anyway. There are good design patterns out there already that demonstrate the best way to split your tiers/layers of code, and this is just a little syntactic sugar so that Microsoft could make the WinForms/WebForms designer files separate and prevent people from breaking them.
我认为无论如何处理这样的问题都不是一个好的选择。已经有很好的设计模式展示了拆分代码层/层的最佳方式,这只是一个小小的语法糖,以便 Microsoft 可以将 WinForms/WebForms 设计器文件分开并防止人们破坏它们。
回答by user47460
While I agree with you Neil when it comes to pre-linq development, I also wish I could be able to do this in order to split up bussiness logic from partial classes generated by Linq2SQL designer. For example:
虽然我同意 Neil 在 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)
Unfortunately, we can not do this... actually I'd love to know what the recommended way of splitting up layers/tiers when using LINQ.
不幸的是,我们不能这样做……实际上,我很想知道在使用 LINQ 时推荐的拆分层/层的方法是什么。
回答by Jason Baker
I can't answer your question about the best way to organize your layers, but I can try to answer your question about how best to emulate partial classes.
我无法回答您关于组织图层的最佳方式的问题,但我可以尝试回答您关于如何最好地模拟部分类的问题。
Here are a few thoughts:
这里有一些想法:
- The first thing that springs to mind is inheritance. It's not necessarily the best solution always, but you may not have a choice since you may need to be able to have your objects be able to be treated like the base class.
- Composition is also a good choice (that is, wrapping the class in another class). This gives you a little bit nicer decoupling from your DAL, but can be tedious to implement.
- If you really just need to add a method or two onto an existing class, you might also consider using an extension method, but these can quickly create spaghetti code if you use them too much.
回答by Johan Nilsson
I see no reason why this scheme would not work:
我看不出为什么这个方案行不通:
Two files contain storage mechanisms (or some other feature). They specify inheritance but contain no business logic:
两个文件包含存储机制(或一些其他功能)。它们指定继承但不包含业务逻辑:
- ProductDataAccess.cs
- ProductWeb.cs
- 产品数据访问.cs
- ProductWeb.cs
One file contains the business logic:
一个文件包含业务逻辑:
- ProductBusinessLogic.cs
- ProductBusinessLogic.cs
Now create two projects:
现在创建两个项目:
- WebProject contains ProductWeb.cs and ProductBusinessLogic.cs.
- DataProject contains ProductDataAccess.cs and ProductBusinessLogic.cs
- WebProject 包含 ProductWeb.cs 和 ProductBusinessLogic.cs。
- DataProject 包含 ProductDataAccess.cs 和 ProductBusinessLogic.cs
Both projects make use of the same business logic.
两个项目都使用相同的业务逻辑。
回答by user3363647
No.You cant write partial classes in different projects.Because at a time compiler gets a single project for compilation and so scans for list of classes,methods,fields etc in that project only.So if you have some parts of the partial class in other projects,compiler cant find those.
不。你不能在不同的项目中编写部分类。因为一次编译器得到一个单独的项目进行编译,所以只扫描该项目中的类、方法、字段等列表。所以如果你有部分类的某些部分其他项目,编译器找不到那些。
回答by Kasper van den Berg
Using Visual Studio 2015 and later it is possibleto split partial classes across projects: use shared projects(see also this MSDN blog).
使用 Visual Studio 2015 及更高版本,可以跨项目拆分部分类:使用共享项目(另请参阅此 MSDN 博客)。
For my situation I required the following:
对于我的情况,我需要以下内容:
- A class library that defines some classes used as interface by several client applications.
- The client application.
- A setup application that creates tables in the database.
Due to limitations of the installer this setup has to be self contained. It cannot reference any assemblies beyond the .NET framework. The setup should insert some enum constants into tables, so ideally it should reference the class library.
The setup can import a Shared Project. - As shared project is similar to copy pasting code, so I want to move as little as possible into the shared project.
- 一个类库,它定义了一些被多个客户端应用程序用作接口的类。
- 客户端应用程序。
- 在数据库中创建表的安装应用程序。
由于安装程序的限制,此设置必须是自包含的。它不能引用 .NET 框架之外的任何程序集。设置应该在表中插入一些枚举常量,因此理想情况下它应该引用类库。
该设置可以导入共享项目。 - 由于共享项目类似于复制粘贴代码,所以我想尽可能少地移动到共享项目中。
The following example demonstrates how partial classes and shared projects allow splitting classes over different projects.
以下示例演示了部分类和共享项目如何允许在不同的项目中拆分类。
In Class Library, Address.cs:
在类库中,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 is a normal Visual Studio Class Library. It imports the SharedProject, beyond that its .csproj contains nothing special:
类库是一个普通的 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
is implemented in the SharedProject:
Address.Direction
在 SharedProject 中实现:
namespace SharedPartialCodeTryout.DataTypes
{
public partial class Address
{
public enum Direction
{
NORTH,
EAST,
SOUTH,
WEST
}
}
}
SharedProject.shproj is:
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>
And its .projitems is:
它的 .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>
The regular client uses Address
including Address.Direction
:
普通客户使用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}");
}
}
}
The regular client csproj references the Class Library and notSharedProject:
常规客户端 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>
The DbSetup uses only the enums:
DbSetup 仅使用枚举:
The DbSetup.csproj does not reference Class Library; it only imports SharedProject:
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>
To conclude:
总结:
Can you split a partial class across projects?
您可以跨项目拆分部分类吗?
Yes, use Visual Studio's Shared Projects.
是的,使用 Visual Studio 的共享项目。
Is it a good idea to write a partial class in a separate project (creating a dependency) using the same namespace?
使用相同的命名空间在单独的项目(创建依赖项)中编写分部类是个好主意吗?
Often not (see the other answers); in some situations and if you know what you are doing it can be handy.
通常不会(请参阅其他答案);在某些情况下,如果您知道自己在做什么,它会很方便。