假设我有一个带有多个函数的脚本,它们采用完全相同的参数,位于相同的位置,并且具有相同的类型和约束,如下所示:
function Verb1-MyValue {
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][String]$Param1,
[parameter(Mandatory = $true)][String]$Param2,
[ValidateSet("Value1","Value2")][String]$Param3 = "Value1"
)
# code ...
}
function Verb2-MyValue {
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][String]$Param1,
[parameter(Mandatory = $true)][String]$Param2,
[ValidateSet("Value1","Value2")][String]$Param3 = "Value1"
)
# code ...
}
# and so on ...
Run Code Online (Sandbox Code Playgroud)
我想param与所有函数共享块以避免潜在的问题(它们需要对所有函数都相同)并避免冗余.
PowerShell中是否有一种方法可以在param同一个脚本中跨多个函数共享块?如果没有,有什么替代品吗?
我知道NuGet包更新过程不是自动的,原因很简单(新版本可能会破坏您的代码或导致无法预料的问题),但随后它将更新所有包的责任转移给开发人员自己.我们究竟应该更新给定项目的NuGet包吗?有关此过程的一些指导原则吗?
在我们当前的项目中,这或多或少是随意的:每当我记得检查更新时,我都会更新软件包,最好是在sprint开始时更新,这样如果新版本出现问题,我们就可以修复它们或者回滚到以前版本的违规包.大多数时候,我是唯一一个担心这些问题的开发人员,但我觉得由于性能原因和新功能可以使我们的工作更轻松,因此始终保持最新状态是很有价值的.
有了StackOverflow的一些帮助,我有Unity Framework来创建我的链接依赖项,包括一个Entity Framework datacontext对象:
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<IMeterView, Meter>();
container.RegisterType<IUnitOfWork, CommunergySQLiteEntities>(new ContainerControlledLifetimeManager());
container.RegisterType<IRepositoryFactory, SQLiteRepositoryFactory>();
container.RegisterType<IRepositoryFactory, WCFRepositoryFactory>("Uploader");
container.Configure<InjectedMembers>()
.ConfigureInjectionFor<CommunergySQLiteEntities>(
new InjectionConstructor(connectionString));
MeterPresenter meterPresenter = container.Resolve<MeterPresenter>();
Run Code Online (Sandbox Code Playgroud)
这非常适合创建我的Presenter对象并显示相关视图,我真的很高兴.
但是,我现在遇到的问题是创建和处理Entity Framework对象的时间(我怀疑这将适用于任何IDisposable对象).像这样使用Unity,SQL EF对象"CommunergySQLiteEntities"是立即创建的,因为我已将其接口IUnitOfWork添加到MeterPresenter的构造函数中
public MeterPresenter(IMeterView view, IUnitOfWork unitOfWork, IRepositoryFactory cacheRepository)
{
this.mView = view;
this.unitOfWork = unitOfWork;
this.cacheRepository = cacheRepository;
this.Initialize();
}
Run Code Online (Sandbox Code Playgroud)
我当时对此感到有点不安,因为我不想保持打开数据库连接,但我看不到使用Unity依赖注入的任何其他方式.果然,当我实际尝试使用datacontext时,我收到此错误:
((System.Data.Objects.ObjectContext)(unitOfWork)).Connection
'((System.Data.Objects.ObjectContext)(unitOfWork)).Connection'
threw an exception of type 'System.ObjectDisposedException'
System.Data.Common.DbConnection {System.ObjectDisposedException}
Run Code Online (Sandbox Code Playgroud)
我对IoC原理的理解是,您将所有依赖项设置在顶部,解决您的对象并远离您.但是,在这种情况下,某些子对象(例如datacontext)不需要在创建父Presenter对象时初始化(就像在构造函数中传递它们一样),但是Presenter确实需要了解IUnitOfWork在与数据库通信时使用的类型.
理想情况下,我想在我解决的Presenter中找到这样的东西:
using(IUnitOfWork unitOfWork = new NewInstanceInjectedUnitOfWorkType())
{
//do unitOfWork stuff
}
Run Code Online (Sandbox Code Playgroud)
因此,Presenter知道IUnitOfWork实现用于直接创建和处理的内容,最好是从原始的RegisterType调用.我是否必须在我的Presenter中放置另一个Unity容器,否则可能会产生新的依赖关系?
对于IoC大师来说,这可能是非常明显的,但我真的很欣赏指向正确方向的指针.
我最近遇到了很多问题,因为包中似乎有一个错误MassTransit.UnityIntegration,主要是因为注册名称没有被考虑.
例如,如果我像这样注册我的类:
var container = new UnityContainer()
.RegisterType<Consumes<Command1>.All, Handler1>("Handler1")
.RegisterType<Consumes<Command1>.All, Handler3>("Handler3");
Run Code Online (Sandbox Code Playgroud)
几行之后,我使用LoadFrom扩展方法来获取容器中的注册使用者,如下所示:
IServiceBus massTransitBus = ServiceBusFactory.New(_sbc =>
{
_sbc.UseBinarySerializer();
_sbc.UseControlBus();
_sbc.ReceiveFrom("msmq://localhost/MyQueue");
_sbc.UseMsmq(_x =>
{
_x.UseSubscriptionService("msmq://localhost/mt_subscriptions");
_x.VerifyMsmqConfiguration();
});
_sbc.Subscribe(_s => _s.LoadFrom(container));
});
Run Code Online (Sandbox Code Playgroud)
当相关消息到达总线时,我的处理程序永远不会被调用.
在思考了一段时间之后,我决定看一下实现,并且很清楚为什么会发生这种情况:
这是方法中的主要代码LoadFrom:
public static void LoadFrom(this SubscriptionBusServiceConfigurator configurator, IUnityContainer container)
{
IList<Type> concreteTypes = FindTypes<IConsumer>(container, x => !x.Implements<ISaga>());
if (concreteTypes.Count > 0)
{
var consumerConfigurator = new UnityConsumerFactoryConfigurator(configurator, container);
foreach (Type concreteType in concreteTypes)
consumerConfigurator.ConfigureConsumer(concreteType);
}
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,它只查找类型,并且不会向前传递任何名称信息.这是FindTypes<T>实施:
static …Run Code Online (Sandbox Code Playgroud) 我需要nuget pack生成一个只有3位数的包版本(我们希望对它进行语义版本控制)但是当我在一个AssemblyVersion属性设置为"1.0.0" 的csproj上调用它时,生成的nupkg文件以版本"1.0结束.0.0"在它的元数据(和文件名)中.为什么命令行工具不支持AssemblyVersion属性上指定的位数?
我通过调用nuget speccsproj文件启动了这个,它生成了一个这样的stub nuspec文件(它实际上包含了带有占位符值的更多标签,但我删除了它们,因为我们不需要它们):
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>Release notes.</releaseNotes>
<copyright>Copyright 2015</copyright>
</metadata>
</package>
Run Code Online (Sandbox Code Playgroud)
将此nuspec文件在TFS中与csproj文件放在同一文件夹中,我们现在可以像这样调用pack:
nuget pack MyProject.csproj
Run Code Online (Sandbox Code Playgroud)
项目的AssemblyInfo.cs文件包含一行显式设置版本:
[assembly: AssemblyVersion("1.0.0")]
Run Code Online (Sandbox Code Playgroud)
除了工具在检索装配版本时使用4位数这一事实外,它完全正常工作.当我右键单击文件浏览器上的dll并转到详细信息时,甚至Windows显示只有3位数的版本.为什么NuGet使用4位数字?我也许错过了一些明显的东西?
对nuspec中的版本进行硬编码显然不是理想的,因为那时我们必须将版本号保持在两个不同的位置,而它们的目的始终是相同的.我的意思是,这应该$version$是NuGet本身知道如何从项目中提取的特殊占位符值背后的想法.
我试图通过使用runsettings文件来限制在TFS中的代码覆盖率过程中分析的程序集,但是即使我明确地将它们排除在外,一些程序集也坚持要进行分析.
这是我目前的runsettings文件内容:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Configurations for data collectors -->
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage"
uri="datacollector://Microsoft/CodeCoverage/2.0"
assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<CodeCoverage>
<ModulePaths>
<Include>
<ModulePath>.*Cloud4Mobile.*</ModulePath>
</Include>
<Exclude>
<ModulePath>.*Tests.dll$</ModulePath>
<ModulePath>.*TestUtilities.dll$</ModulePath>
</Exclude>
</ModulePaths>
<CompanyNames>
<Include>.*Mobiltec.*</Include>
</CompanyNames>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
Run Code Online (Sandbox Code Playgroud)
但是,当我从Visual Studio运行代码覆盖率来测试此文件时,分析仍然显示其他与我的过滤器不匹配的程序集,如AutoMapper和CacheManager:

请注意,默认情况下,我的设置已经排除了这些程序集,但即使这样,我也尝试明确地将它们排除在无效之外,如下所示:
<Exclude>
<ModulePath>^AutoMapper.dll$</ModulePath>
...
</Exclude>
Run Code Online (Sandbox Code Playgroud)
我尝试了正则表达式的所有变体,从限制较少(使用.*)到限制性最强(如该示例).这些程序集污染了我在TFS构建摘要中获得的报告,我想将它们从分析中删除.这是我从TFS获得的完整输出,这显然是无用的:

我设法使用此.runsettings配置文件删除了大部分内容,但是如何确保这些异常值也不会显示在那里?为什么他们甚至首先显示,考虑到它们与我的包含过滤器完全匹配?
我的程序中有一个概念Room.每个房间都有一些Users,每个用户都有一个Observable说明他想要在房间里达到什么程度的沉默.当用户选择一个新值时,我只需通过调用类中OnNext的内部BehaviorSubject实例将其推送到Observable User.
该计划的主要逻辑是,人们应该能够告诉房间需要什么级别的沉默.例如,如果房间中至少有一个用户需要保持沉默,则整个房间需要保持沉默.
这是我的课程的简化:
首先,我使用枚举来表示可能的声级.现在只有两个值:
enum SoundLevelRequirement
{
/// <summary>
/// Indicates that the user is ok with any sound level in the room.
/// </summary>
None,
/// <summary>
/// Indicates that the user needs absolute silence in the room.
/// </summary>
Silence
}
Run Code Online (Sandbox Code Playgroud)
用户只需公开一个Observable,只要状态发生变化就会触发.
class User
{
private readonly BehaviorSubject<SoundLevelRequirement> soundLevel;
public User(string name)
{
Name = name;
soundLevel = new BehaviorSubject<SoundLevelRequirement>(SoundLevelRequirement.None);
}
public string Name { get; …Run Code Online (Sandbox Code Playgroud) 我在使用 EventBridge 服务将 AWS 状态机返回的值之一作为输入传递到 Lambda 时遇到问题。
我在 AWS Step Functions 中创建了一个状态机来对我们域中的特定问题进行建模。状态机完成后,我想从其中一个 Lambda 内部执行另一项操作。为了实现这一点,我使用 EventBridge 创建了一条新规则:每当状态机完成时,它都会使用特定的 Json 输入触发我的 lambda。
我的问题是如何从状态机输出中提取属性并将它们作为 lambda 输入的属性传递。
假设我的状态机返回以下内容:
{
"usefulObject":{
"usefulProperty":"value"
},
"anotherProperty":"anotherValue"
}
Run Code Online (Sandbox Code Playgroud)
我想在我的 lambda 中接收以下有效负载:
{
"property":"value"
}
Run Code Online (Sandbox Code Playgroud)
最初,我认为我可以使用 EventBridge 规则上的“输入转换”选项来完成此操作,例如:
{"propertyValue":"$.usefulObject.usefulProperty"}
Run Code Online (Sandbox Code Playgroud)
{"property":<propertyValue>}
Run Code Online (Sandbox Code Playgroud)
然而,在测试过程中,我意识到事件有效负载包含的数据比状态机输出多得多。实际上,状态机输出被包装在这个“事件容器”对象中,如下所示:
{
"version": "0",
"id": "...",
"detail-type": "Step Functions Execution Status Change",
"source": "aws.states",
"account": "...",
"time": "2020-11-10T13:59:57Z",
"region": "us-east-1",
"resources": [
"...myStateMachineArn..."
],
"detail": {
"executionArn": "...myStateMachineExecutionArn...",
"stateMachineArn": "...myStateMachineArn...",
"name": "ff72036a-2917-c657-80e7-2589b7b76d59",
"status": "SUCCEEDED",
"startDate": 1605016794597,
"stopDate": 1605016797936, …Run Code Online (Sandbox Code Playgroud) json jsonpath aws-lambda aws-step-functions aws-event-bridge
我们的其中一个解决方案中有几个 html 页面,这些页面非常简单,仅限客户端,纯 html+javascript 页面可以访问我们的 web api。api 本身位于同一解决方案中的 Web 应用程序项目中。
我们现在正在使用一个网站项目来包含这些文件,但是管理该项目变得越来越难,因为它的信息放在解决方案上,而且它的大部分方面都无法像在 msbuild 项目文件中那样进行控制.
我想将这些 html 文件迁移到 Web 应用程序项目,但我正在努力使其尽可能基本。例如,我不想在项目上生成任何 dll。它应该在解决方案中只是提供对文件的访问,并使我们能够通过在_PublishedWebsites文件上设置构建操作来控制构建文件夹的内容。我们需要这个是因为项目中有一些不应该发布的杂项文件。
我尝试通过编辑 csproj 文件来创建一个空的 Web 应用程序并从中删除大部分内容。我设法删除了所有引用和整个Properties特殊文件夹(以及 AssemblyInfo.cs 文件),但是当我运行该build命令时,我仍然看到obj与bin文件夹一起创建的 dll 。然后,我尝试在 csproj 文件上伪造构建目标,如下所示:
<Target Name="Build" />
Run Code Online (Sandbox Code Playgroud)
现在当项目构建时,没有创建 dll/pdb,但 obj 和 bin 文件夹仍然存在。接下来,我尝试将 outputpath 属性设置为当前目录,如下所示:
<OutputPath>.</OutputPath>
Run Code Online (Sandbox Code Playgroud)
但即便如此,仍会创建 obj 文件夹。
编辑:
我刚刚发现了另一个常见的 msbuild 属性,它控制 obj 文件夹中的文件的放置位置。将其放入我的 csproj 文件后:
<IntermediateOutputPath>.</IntermediateOutputPath>
Run Code Online (Sandbox Code Playgroud)
我现在在构建时没有生成文件夹,这很好。
但是,当我打开解决方案或在 Visual Studio 中重新加载项目时,现在有一个小问题(我不确定这个过程是如何发生的以及发生在何处)。即使此时未构建项目,仍会生成一些文件:

我觉得目前的方法足以满足我的要求,但我真的很想知道是否有更优雅的方法来实现这一点。因此,问题是:有没有办法让 Web 应用程序项目像没有代码文件一样工作,有效地禁用输出生成(bin 和 obj 文件夹,以及 dll/xml/pdb 输出)?
.net ×3
nuget ×2
tfsbuild ×2
aws-lambda ×1
esb ×1
html ×1
json ×1
jsonpath ×1
masstransit ×1
msbuild ×1
nuget-spec ×1
parameters ×1
parent-child ×1
powershell ×1
runsettings ×1
tfs ×1
updates ×1