我试图理解装饰器模式,从实例中我理解装饰器对象如何通过覆盖装饰对象的方法以及如何通过新方法实现添加其他功能来在运行时扩展现有功能.
我有点困惑的地方是使用多个装饰器以及如何访问扩展功能.通常,在查看装饰器模式的示例时,会显示以下内容:
IBusinessObject businessObject = new MailDecorator(
new SmsDecorator(
new FaxDecorator(
new BusinessObject()
)
)
);
Run Code Online (Sandbox Code Playgroud)
想法是采取一个对象并动态添加邮件,短信和传真功能.现在,如果您想发送邮件,这是MailDecorator类提供的方法,您可以执行以下操作:
If(businessObject is MailDecorator)
{
((MailDecorator) businessObject).SendMail();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您想要发送短信或传真,就像在装饰器模式的正常实现中那样,您将无法访问装饰器引用的对象,这将无效.
这是装饰器模式的限制还是超出了你可以期望用这种模式实现的范围,还是我完全误解了这里的东西?
不同的模式会更合适吗?
标准定义
"动态地将附加职责附加到对象.装饰器为子类提供了灵活的替代方案,可以扩展功能"
意味着这应该可以通过这种模式实现,但在一个对象上使用多个装饰器时似乎会崩溃.
我正在努力确保我的编码遵循正确的对象处理方式,因此我将这些规则强制执行为错误.但我在使用这段代码时遇到了麻烦
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
class MyClass
{
public String ToXml()
{
var objSerializer =
new DataContractSerializer(GetType());
var objStream = new MemoryStream();
StreamReader objReader;
String strResult;
try
{
// Serialize the object
objSerializer.WriteObject(objStream, this);
// Move to start of stream to read out contents
objStream.Seek(0, SeekOrigin.Begin);
objReader = new StreamReader(objStream);
try
{
// Read Contents into a string
strResult = objReader.ReadToEnd();
}
finally
{
objReader.Dispose();
}
}
finally
{
if (objStream != null)
{
// objStream.Dispose(); …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用SimpleInjector作为IOC容器,到目前为止我对此非常满意.但是现在我遇到了一个我无法解决的问题.我搜索了SO和文档,但似乎还没有回答.我已经看过SimpleInjector的howto doc但是它没有涵盖开放的通用接口.
我有两个这样的通用接口:
public interface IEventPublisher<TEvent>
{
void Publish(TEvent Event);
}
public interface IEventSubscriber<TEvent>
{
void Subscribe(Action<TEvent> CallBack);
}
Run Code Online (Sandbox Code Playgroud)
这两个开放的通用实现:
class EventMediator<T> : IEventPublisher<T>, IEventSubscriber<T>
{
List<Action<T>> Subscriptions = new List<Action<T>>();
public void Publish(T Event)
{
foreach (var Subscription in this.Subscriptions)
Subscription.Invoke(Event);
}
public void Subscribe(Action<T> CallBack)
{
this.Subscriptions.Add(CallBack);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的应用程序中,我正在设置SimpleInjector,如下所示:
this.Container = new SimpleInjector.Container();
this.Container.RegisterOpenGeneric(typeof(IEventPublisher<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.RegisterOpenGeneric(typeof(IEventSubscriber<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.Verify();
Run Code Online (Sandbox Code Playgroud)
我想要存档的是:在要求IEventPublisher或IEventSubscriber时,我想获得完全相同的实例.此外,此实例应为任何T的单例.
我用这些线测试了这个:
class DummyEvent {}
var p = this.Container.GetInstance<IEventPublisher<DummyEvent>>();
var s = this.Container.GetInstance<IEventSubscriber<DummyEvent>>();
var areSame …Run Code Online (Sandbox Code Playgroud) 编辑:我正在学习依赖注入.我理解在开发大型系统时它至关重要的基本原因.
似乎依赖注入使用反射来实现其一些目标.反思是一种逆向工程(可能只对我而言).
如果有人解释为什么以及如何使用Reflection以及它是否是可选的,那将对我非常有帮助.
我正在尝试按照Jimmy Bogard的这篇文章来实现一个中介管道,这样我就可以使用前/后请求处理程序来完成一些工作.从那篇文章的评论中,我来到这个github要点.我不太明白如何挂钩所有这些,所以这是我的第一次去.仅供参考 - 我正在使用Autofac进行DI和Web Api 2.遵循CQRS,这是一个查询.
public class GetAccountRequest : IAsyncRequest<GetAccountResponse>
{
public int Id { get; set; }
}
//try using fluent validation
public class GetAccountRequestValidationHandler
: AbstractValidator<GetAccountRequest>, IAsyncPreRequestHandler<GetAccountRequest>
{
public GetAccountRequestValidationHandler() {
RuleFor(m => m.Id).GreaterThan(0).WithMessage("Please specify an id.");
}
public Task Handle(GetAccountRequest request) {
Debug.WriteLine("GetAccountPreProcessor Handler");
return Task.FromResult(true);
}
}
public class GetAccountResponse
{
public int AccountId { get; set; }
public string Name { get; set; }
public string AccountNumber { get; set; …Run Code Online (Sandbox Code Playgroud) 可以手动注册依赖项:
services.AddTransient<IEmailService, EmailService>();
services.AddTransient<ISmsService, SmsService>();
Run Code Online (Sandbox Code Playgroud)
当依赖关系太多时,手动注册所有依赖项变得很困难.
在MVC 6(beta 7)中实现基于约定的绑定的最佳方法是什么?
PS在我以前使用的项目Ninject有ninject.extensions.conventions.但我找不到适用于MVC 6的Ninject适配器.
c# dependency-injection ninject asp.net-core-mvc asp.net-core
我正在使用简单的注射器3.0.4
我有一种服务,其生活方式取决于具有短暂生活方式的服务.
当我调用container.Verify()时,我得到一个关于生活方式不匹配的诊断错误.
导致问题的瞬态服务被注入到其他临时服务中,所以在我开始使用整个项目范围之前我需要问一下.为什么从任何生活方式的范围到短暂的依赖都是一个问题?每次注射瞬态时都会新鲜出现,所以没有其他任何东西可以干扰它.本质上,瞬态对象的生命周期由它注入的服务控制.
此外,我已经从这里阅读了有关此主题的文档,并且我确实理解为什么您不希望单例依赖于作用域服务,但是对瞬态的依赖总是安全的?
我刚刚遇到了垃圾收集者的这种奇怪的"行为" System.Threading.ThreadLocal<T>,我无法解释.在正常情况下,ThreadLocal<T>实例将在超出范围时进行垃圾收集,即使它们没有正确处理,除非它们是循环对象图的一部分.
以下示例演示了此问题:
public class Program
{
public class B { public A A; }
public class A { public ThreadLocal<B> LocalB; }
private static List<WeakReference> references = new List<WeakReference>();
static void Main(string[] args) {
for (var i = 0; i < 1000; i++)
CreateGraph();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
// Expecting to print 0, but it prints 1000
Console.WriteLine(references.Count(c => c.IsAlive));
}
static void CreateGraph() {
var a = new A { LocalB = new ThreadLocal<B>() }; …Run Code Online (Sandbox Code Playgroud) 出于某种奇怪的原因,只有使用完整的CLR才能使用System.Runtime.Remoting.Messaging.CallContext和AsyncLocal类.这使得在使用可移植类库或Windows Phone应用程序时进行异步作用非常困难,特别是因为Windows Phone API变得异步; 所以我们没有选择不使用async/await.
这实际上意味着在WPF或WinForms中,我们可以编写如下方法:
private async void button_Click(object sender, EventArgs e)
{
CallContext.LogicalSetData("x", new object());
await Something();
var context = CallContext.LogicalGetData("x");
}
Run Code Online (Sandbox Code Playgroud)
在WPF和WinForms中,框架确保每次单击到同一个按钮都可以获得自己的上下文,并且可以单独运行.很难实现相同的使用ThreadLocal<T>,[ThreadStatic]因为每次点击都会在UI线程上执行.
我的问题是,我们如何将Windows Phone中,商店和其他应用程序类型的解决这个问题,不支持CallContext和AsyncLocal<T>?
一些背景资料:
我们经常希望(业务)逻辑在某种上下文中运行.此上下文可以包含业务逻辑在整个操作中可以使用的信息.在服务器环境中,这很容易想象,因为您需要在数据库事务中运行请求,需要访问当前用户,租户ID等.但即使在客户端应用程序中,操作也可能需要访问上下文信息,例如用于记录的当前运行操作或上下文的相关ID.在此类操作期间(如点击事件),我们可能需要解析其他服务(来自我们的合成根).为了使操作成功,我们可能需要在整个客户端操作中重用相同的组件,这意味着我们的组合根需要知道它正在运行的上下文.
虽然所有这些信息都可以使用服务公共API的方法调用在整个系统中传递,但这不仅会迫使我们使用实现细节污染应用程序中的服务API,还会导致严重的维护问题,因为我们必须在整个系统中传递所有这些信息,并且对我们的一个组件的简单内部更改将通过所有方法调用向上传播调用堆栈.当涉及到我们的Composition Root时,我们绝对不希望通过应用程序传递我们的DI库的一些缓存/范围对象,因为这会将我们的业务逻辑紧密地耦合到外部库.显然,我们也不想传递某种服务定位器.
因此,在客户端应用程序中使用类似CallContext或AsyncLocal<T>非常重要的实现范围.
如何在Asp.Net 5 RC1中登录文件?我找不到Microsoft.Extensions.Logging的任何解决方案.有没有与.Net Core 5(DNX Core 5.0)兼容的解决方案?我也试图使用Serilog,但Serilog还不支持核心5.