直到今天,我对.NET Tuple
类的理解是他们将他们的实现委托Equals()
给他们的内容,允许我将它们等同并"按值"进行比较.
然后这个测试出现了,让我变得愚蠢:
[TestMethod]
public void EquateTwoTuplesWithSameContent()
{
var t1 = Tuple.Create("S");
var t2 = Tuple.Create((object)t1.Item1);
Assert.IsTrue(t1.Equals(t2)); // Boom!
}
Run Code Online (Sandbox Code Playgroud)
阅读MSDN文档和各种博客给我留下了更多问题.从我收集的内容来看,似乎Tuple<object>
并且Tuple<TWhatever>
总是被认为是不相等的,无论两个实例都可以包装相同的对象(盒装或类型转换 - 它们都是相同的).
这真的Tuples
应该如何表现?结构兼容性实际上是对平等的另一个限制,而不是放松,因为我一直在解释它直到现在?
如果是这样,BCL中还有什么可以用来满足上述单元测试的期望吗?
先感谢您!
我很好奇是否有办法在新进程中执行静态.DLL方法而不必为它创建.EXE?
AFAIK,本机Win32/64 DLL无法实现..NET DLL程序集怎么样?
更新:我忘了提到我主要感兴趣的是以编程方式执行此操作(来自C#代码,具体而言).
谢谢!
结论:虽然没有人"敢"拼出来,但答案似乎都倾向于"不".需要通过一种传统方式(EXE,PowerShell等)启动进程,然后说服进程加载DLL并执行其中的代码.我想我错误地希望托管的DLL能够提供更多功能.
再次感谢所有插话的人!
是否可以将lambda表达式作为IL字节流传递给辅助AppDomain,然后使用DynamicMethod将其组装回那里,以便可以调用它?
我不太确定这是一个正确的方法,所以这是(详细的)原因我问这个问题...
在我的应用程序中,有很多情况需要加载几个程序集进行反射,因此我可以确定接下来要对它们做些什么.问题部分是我需要能够在完成反射之后卸载组件.这意味着我需要使用另一个加载它们AppDomain
.
现在,我的大多数情况都有点类似,但不完全相同.例如,有时我需要返回一个简单的确认,有时我需要从程序集中序列化资源流,有时我还需要进行一两次回调.
因此,我最终AppDomain
一遍又一遍地编写相同的半复杂临时创建代码,并实现自定义MarshalByRefObject
代理以在新域和原始域之间进行通信.
由于这不再是可以接受的,我决定编写一个AssemblyReflector
可以这样使用的类:
using (var reflector = new AssemblyReflector(@"C:\MyAssembly.dll"))
{
bool isMyAssembly = reflector.Execute(assembly =>
{
return assembly.GetType("MyAssembly.MyType") != null;
});
}
Run Code Online (Sandbox Code Playgroud)
AssemblyReflector
将AppDomain
凭借自动卸载IDisposable
,并允许我执行一个透明地Func<Assembly,object>
将反射代码保存在另一个中的-type lambda AppDomain
.
问题是,lambdas不能简单地传递给其他域.所以在搜索之后,我发现看起来像是一种方法:将lambda传递给新AppDomain
的IL作为IL流 - 这让我想到了原始问题.
这是我尝试过的,但没有用(BadImageFormatException
在尝试调用新委托时问题被抛出):
public delegate object AssemblyReflectorDelegate(Assembly reflectedAssembly);
public class AssemblyReflector : IDisposable
{
private AppDomain _domain;
private string _assemblyFile;
public AssemblyReflector(string fileName) { ... }
public void Dispose() { ... …
Run Code Online (Sandbox Code Playgroud) 我正在尝试为我的UserControl添加叠加效果,我知道这是在WPF中使用的装饰器.但我对他们认为如何工作有点困惑.我认为adorner层是由WPF运行时隐式处理的,因此应始终可用.
但是当我在代码中创建UserControl的实例时,那里没有adorner层.以下代码失败,但有异常:
var view = new MyUserControl();
var target = view.GetAdornerTarget(); // This returns a specific UI control.
var layer = AdornerLayer.GetAdornerLayer(target);
if (layer == null)
{
throw new Exception("No adorner layer at the moment.");
}
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释,这应该如何运作?我是否需要先将UserControl实例放入顶级窗口?或者我是否需要以某种方式自己定义图层?挖掘文档让我无处可去.
谢谢!
我正在尝试使用MVVM(Model-View-ViewModel)模式实现WPF应用程序,并且我希望View部件位于Model和ViewModel部件(DLL)的单独程序集(EXE)中.
这里的转折是保持Model/ViewModel程序集清除任何WPF依赖项.这样做的原因是我想从具有不同(非WPF)UI技术的可执行文件中重用它,例如Mono下的WinForms或GTK#.
默认情况下,无法执行此操作,因为ViewModel公开了一个或多个ICommands.但ICommand类型是在System.Windows.Input命名空间中定义的,该命名空间属于WPF!
那么,有没有办法在不使用ICommand的情况下满足WPF绑定机制?
谢谢!
我有一个针对.NET 4.6的ASP.NET应用程序,我疯狂地试图找出为什么HttpContext.Current
在我的异步MVC控制器操作中第一次等待之后变为null.
我检查并三重检查我的项目是针对v4.6,web.config的targetFramework
属性也是4.6.
SynchronizationContext.Current
在await之前和之后分配,它是正确的,即AspNetSynchronizationContext
不是遗留的.
FWIW,await有问题确实在继续时切换线程,这可能是由于它调用外部I/O绑定代码(异步数据库调用)但这应该不是问题,AFAIU.
然而,它是!HttpContext.Current
变为null 的事实导致我的代码出现了许多问题,对我来说没有任何意义.
我检查了通常的建议,我很肯定我正在做我应该做的一切.我的代码中也完全没有ConfigureAwait
!
我所拥有的是,我的HttpApplication
实例上有几个异步事件处理程序:
public MvcApplication()
{
var helper = new EventHandlerTaskAsyncHelper(Application_PreRequestHandlerExecuteAsync);
AddOnPreRequestHandlerExecuteAsync(helper.BeginEventHandler, helper.EndEventHandler);
helper = new EventHandlerTaskAsyncHelper(Application_PostRequestHandlerExecuteAsync);
AddOnPostRequestHandlerExecuteAsync(helper.BeginEventHandler, helper.EndEventHandler);
}
Run Code Online (Sandbox Code Playgroud)
我需要这两个因为自定义授权和清理逻辑,这需要异步.AFAIU,这是支持的,不应该是一个问题.
还有什么可能是我看到这种令人费解的行为的原因?
更新:补充观察.
SynchronizationContext
在等待与等待之前,引用保持不变.但它的内部变化在下面的截图中可以看到!
我不确定这与我的问题有什么关系(或者甚至是否).希望别人能看到它!
我在使用以下代码时遇到了一些问题:
private class ClientPluginLoader : MarshalByRefObject
{
public bool IsPluginAssembly(string filename)
{
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomainReflectionOnlyAssemblyResolve);
Assembly asm = Assembly.ReflectionOnlyLoadFrom(filename);
Type[] types = asm.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(ClientPlugin)))
{
return true;
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
代码是通过我通过自定义应用程序域的CreateInstanceFromAndUnwrap()创建的代理调用的.这意味着IsPluginAssembly()在我的自定义应用程序域的上下文中执行.
问题是对IsSubclassOf()的调用总是返回false,即使它应该返回true.所讨论的"类型"确实从ClientPlugin继承 - 毫无疑问.
ClientPlugin是在一个不同的私有程序集中定义的,我正在手动解析,如上面的代码片段所示.
我在线上放了一个断点if (type.IsSubclassOf(...))
并确认这个表达式是假的:
type.BaseType == typeof(ClientPlugin)
Run Code Online (Sandbox Code Playgroud)
另一方面,这个表达式是正确的:
type.BaseType.FullName == typeof(ClientPlugin).FullName
Run Code Online (Sandbox Code Playgroud)
这怎么可能?这是怎么回事?
更新:Kent Boogaart向我指出了正确的方向.我在网上搜索了一下,然后进入这篇博文.我似乎必须解决我的Load/LoadFrom/ReflectionOnlyLoadFrom冲突才能使其工作.
我有一个自定义任务,我想在构建我的C#项目时执行.此任务位于MyTask.dll中,它引用另一个程序集MyCommon.DLL.
问题是MyCommon.dll位于相对于MyTask.dll的"..\Common\MyCommon.dll",它将它放在AppBase目录之外,用于MSBuild进程.我已经通过分析MSBuild的日志并看到Fusion关于绑定失败的报告确认这确实是问题.
如何在构建过程中使Fusion找到MyCommon.dll?请注意,移动程序集会破坏我的应用程序,这也取决于它.
更新:嗯,似乎我会继续使用复制品.其他解决方案都需要系统范围的修改,这在这里并不是真正的保证.
我希望这个问题不被认为过于主观 - 我真的不期待一个明确的答案,但我希望每个人的意见至少能帮助我形成自己的意见.
我正在实现一个自定义类型系统,它是经典OOP类型系统的超集.在这种类型的系统中,对象实例可以在运行时组合以形成新的实例,同时保留个体身份.
这段代码:
var p = new Person();
var pa = new Partner(p);
Run Code Online (Sandbox Code Playgroud)
...产生单个组合对象,其中"p"和"pa"是不同的符合OOP的视图.IOW,更改其中一个视图的属性值会立即反映在同时包含此属性的任何其他视图上.
这一切都运行良好,但它缺少两个用于查询类型标识的关键API.我真的希望能够编写这样的代码:
if (p is Partner)
{
(p as Partner).SomePartnerProperty = "...";
}
Run Code Online (Sandbox Code Playgroud)
这当然不起作用,因为"is"和"as"操作符的行为不能超出/扩展超出.NET的OOP规则所要求的范围.尽管如此,我仍然需要在我的类型系统中使用此功能.
我的第一个想法是使用附加到我的类型系统的所有实例的通用扩展方法:
public static bool Is<T>(this BaseType target) where T : BaseType { ... }
public static T As<T>(this BaseType target) where T : BaseType { ... }
Run Code Online (Sandbox Code Playgroud)
忽略不区分大小写的语言中的名称冲突问题,这在功能方面似乎没问题:
if (p.Is<Partner>())
{
p.As<Partner>().SomePartnerProperty = "...";
}
Run Code Online (Sandbox Code Playgroud)
但是,我不禁想知道 - 这真的是最好的,最方便的API吗?
您如何建议我实现这两个操作符,以便在应用程序代码中使用它们自然?
更新:对于任何想知道这种类型系统的目的的人......基本上,每种类型都属于两类:身份或角色.在我上面给出的示例中,Person是一个Identity(按设计),而Partner是一个Role(再次,通过设计 - 它的设计可能不同).这种类型的系统的基本规则是,任何数量的角色可以与任何给定的身份组成,而身份本身可能只用一个更高的身份组成(例如一个人有可能成为一个联系,但绝不能成为公司).这种类型系统使应用程序能够透明地处理例如合作伙伴对象,而不管他们拥有什么身份(例如,人员,公司,银行等).
阅读这个问题的答案促使我思考在等待任务抛出时异常情况发生了什么.所有"客户"都可以观察异常吗?我承认我可能会在这里混淆几件事; 这就是我要求澄清的原因.
我将介绍一个具体的场景......假设我有一个服务器,其中包含Task
由客户端启动的长期运行实例的全局集合.在启动一个或多个任务后,客户端可以查询其进度并在结果可用时检索结果,以及可能发生的任何错误.
任务本身可以执行非常不同的业务特定事物 - 通常,没有两个是完全相同的.但是,如果其中一个客户端尝试启动与先前启动的另一个客户端相同的任务,则服务器应识别此并将第二个客户端"附加"到现有任务,而不是假脱机新副本.
现在,每当任何客户端查询它感兴趣的任务的状态时,它都会按照以下方式执行:
var timeout = Task.Delay(numberOfSecondsUntilClientsPatienceRunsOut);
try
{
var result = await Task.WhenAny(timeout, task);
if (result == timeout)
{
// SNIP: No result is available yet. Just report the progress so far.
}
// SNIP: Report the result.
}
catch (Exception e)
{
// SNIP: Report the error.
}
Run Code Online (Sandbox Code Playgroud)
简而言之,它为任务提供了一些合理的时间来完成它首先完成的工作,然后回过头来报告正在进行的进展.这意味着有一个潜在的重要时间窗口,多个客户端可以观察到相同的任务失败.
我的问题是:如果任务恰好在此窗口期间抛出,是否所有客户端都会观察(和处理)异常?
c# ×6
.net ×2
appdomain ×2
task ×2
wpf ×2
adorner ×1
asp.net ×1
assemblies ×1
async-await ×1
asynchronous ×1
cil ×1
equality ×1
fusion ×1
lambda ×1
msbuild ×1
mvvm ×1
reflection ×1
tuples ×1
type-systems ×1
types ×1