john's tech blog

hope is coming


  • 首页

  • 标签

  • 归档

csharp-classinitorder

发表于 2015-10-30 | 更新于 2019-05-09

读了Java重写方法与初始化的隐患这篇文章,带着对C#初始化的疑问,在C#里做了如下测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class BaseClass
{
//4
private int mSuperX = 2;

//3
private static int ms = 2;

//5
public BaseClass()
{
//调用了子类setX
setX(99);
}

public virtual void setX(int x) {
mSuperX = x;
}
}

public class SubClass : BaseClass {

//2
private int mSubX = 1;

//1
private static int m = 2;

//6
public SubClass()
{
}

public override void setX(int x) {
base.setX(x);
mSubX = x;
Console.WriteLine("SubX is assigned " + x);
}

public void printX() {
Console.WriteLine("SubX = " + mSubX);
}

so,C#里面 子类static成员 -> 子类普通成员初始化和初始化块 ->父类static成员 -> 父类static成员 -> 父类普通成员初始化和初始化块 -> 父类构造方法 ->子类构造方法。

recent-feelonwork

发表于 2015-10-29 | 更新于 2019-05-09

遇到的问题:

1.git和svn的区别
2.webservice和wcf的区别

这两个问题促使我在对框架和工具的使用中必须要反思不能只知道使用而不知道去理解,
就像只会去学习使用编程语言而不知道去理解语言之间的异同和在开发项目时应该选择哪种语言更合适。

3.调试项目代码遇到的问题。

在开发过程中只保证进度而不思考和立即改进现有代码和设计导致在部署后很难通过简单的测试,而且不能立即定位问题所在。这会带来时间上的浪费。

归根于代码上的设计不够严谨 应该要把逻辑中可能出现的异常反馈到日志,从而对数据非预期展现的快速定位。

csharp-generichandler

发表于 2015-10-20 | 更新于 2019-05-09

C# 泛型委托书写

###

1
2
3
4
5
6
7
8
//先声明泛型委托
public delegate T GetHandler<T>(string propertyName,T t);

//再定义
GetHandler<string> strHandler = new GetHandler<string>((ss, s) => { return ""; });

//再调用
string str = strHandler("Id", "ss");

csharp-reflectproperty

发表于 2015-10-20 | 更新于 2019-05-09

C#反射Encoding.UTF8属性

###

1.0源码:

1
2
3
4
5
6
7
8
9
10
11
//先获取UTF8静态属性
PropertyInfo property = typeof(Encoding).GetProperty("UTF8", BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.Public);
//获取属性值
object objUTF8 = property.GetValue(null,null);
//获取GetString函数列表
IEnumerable<MethodInfo> infos = typeof(Encoding).GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(m => m.IsVirtual && m.Name == "GetString");

byte[] bys = new byte[] {};
//调用第一个GetString函数
object obj = infos.First().Invoke(objUTF8, new object[] { bys });

orchard-events

发表于 2015-10-08 | 更新于 2019-05-09

Orchard的Events是如何驱动的

ShellDescriptorManager类

ShellDescritorManager有个UpdateShellDescriptor方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void UpdateShellDescriptor(int priorSerialNumber, IEnumerable<ShellFeature> enabledFeatures, IEnumerable<ShellParameter> parameters) {
ShellDescriptorRecord shellDescriptorRecord = GetDescriptorRecord();
var serialNumber = shellDescriptorRecord == null ? 0 : shellDescriptorRecord.SerialNumber;
if (priorSerialNumber != serialNumber)

throw new InvalidOperationException(T("Invalid serial number for shell descriptor").ToString());

if (shellDescriptorRecord == null) {
shellDescriptorRecord = new ShellDescriptorRecord { SerialNumber = 1 };
_shellDescriptorRepository.Create(shellDescriptorRecord);
}

else {
shellDescriptorRecord.SerialNumber++;
}


shellDescriptorRecord.Features.Clear();
foreach (var feature in enabledFeatures) {

shellDescriptorRecord.Features.Add(new ShellFeatureRecord { Name = feature.Name, ShellDescriptorRecord = shellDescriptorRecord });
}


shellDescriptorRecord.Parameters.Clear();
foreach (var parameter in parameters) {

shellDescriptorRecord.Parameters.Add(new ShellParameterRecord {
Component = parameter.Component,
Name = parameter.Name,
Value = parameter.Value,
ShellDescriptorRecord = shellDescriptorRecord
});

}

_events.Changed(GetShellDescriptorFromRecord(shellDescriptorRecord), _shellSettings.Name);
}

看最后的_events.Changed 是调用了IShellDescriptorManagerEventHandler接口的Changed方法。
那为什么一个EventHandler会命名为_events呢?答案在EventsRegistrationSource类中

EventsRegistrationSource类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) {
var serviceWithType = service as IServiceWithType;
if (serviceWithType == null)
yield break;

var serviceType = serviceWithType.ServiceType;
if (!serviceType.IsInterface || !typeof(IEventHandler).IsAssignableFrom(serviceType) || serviceType == typeof(IEventHandler))
yield break;

//interface proxy with target其实跟class proxy差不多,在创建代理对象时client指定接口,并且提供一个实现了该接口的对象作为真实对象,DP将创建这个接口的代理对象,对代理对象方法的调用经过拦截器处理之后,最终将调用真实对象相应的方法。与class proxy的不同之处在于,真实对象的方法不必是virtual类型也可以实现拦截
//interface proxy without target比较特殊,创建代理时只需要指定一个接口就可以,DP自动根据接口构造一个实现的类,作为代理对象的类型,但这个代理类只能用于拦截目的,无法像class proxy一样在拦截器中调用真实对象的处理方法。比如在提供了多个拦截器时,最后一个拦截器的接口方法中不能调用invocation.Proceed()方法,否则会抛异常(因为真实对象根本不存在,只有一个假的代理对象)
var interfaceProxyType = _proxyBuilder.CreateInterfaceProxyTypeWithoutTarget(
serviceType,
new Type[0],
ProxyGenerationOptions.Default);

//关于代理
//http://www.cnblogs.com/leiwei/p/3456695.html
//http://www.cnblogs.com/RicCC/archive/2010/03/15/castle-dynamic-proxy.html
//http://www.cnblogs.com/Tyrale/archive/2009/06/29/1512907.html

var rb = RegistrationBuilder
.ForDelegate((ctx, parameters) => {
var interceptors = new IInterceptor[] { new EventsInterceptor(ctx.Resolve<IEventBus>()) };
var args = new object[] { interceptors, null };
return Activator.CreateInstance(interfaceProxyType, args);
})
.As(service);

yield return rb.CreateRegistration();
}

在构造器中指定了拦截器 EventsInterceptor ,拦截器又传入了EventBus.

EventsInterceptor类

我们来看看拦截方法是怎样的:

1
2
3
4
5
6
7
8
9
10
11
12
public void Intercept(IInvocation invocation) {
var interfaceName = invocation.Method.DeclaringType.Name;
var methodName = invocation.Method.Name;

var data = invocation.Method.GetParameters()
.Select((parameter, index) => new { parameter.Name, Value = invocation.Arguments[index] })
.ToDictionary(kv => kv.Name, kv => kv.Value);

var results = _eventBus.Notify(interfaceName + "." + methodName, data);

invocation.ReturnValue = Adjust(results, invocation.Method.ReturnType);
}

调用了eventBus的Notify方法

DefaultOrchardEventBus类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public IEnumerable Notify(string messageName, IDictionary<string, object> eventData) {
// call ToArray to ensure evaluation has taken place
return NotifyHandlers(messageName, eventData).ToArray();
}
//IDictionary<string, object>型参数包含调用方法时要传递的参数
//接口名称和方法名称查找某一个类型的方法并调用
private IEnumerable<object> NotifyHandlers(string messageName, IDictionary<string, object> eventData) {
string[] parameters = messageName.Split('.');
if (parameters.Length != 2) {
throw new ArgumentException(T("{0} is not formatted correctly", messageName).Text);
}
string interfaceName = parameters[0];//接口名称
string methodName = parameters[1];//方法名称

var eventHandlers = _eventHandlers();
foreach (var eventHandler in eventHandlers) {
IEnumerable returnValue;
if (TryNotifyHandler(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue)) {
if (returnValue != null) {
foreach (var value in returnValue) {
yield return value;
}
}
}
}
}

其实就是调用了各个实现IEventHandler接口的类。

1…44454647

John

232 日志
43 标签
GitHub Twitter
欢迎关注我的公众号:沉迷Spring
© 2023 johnwonder
由 Hexo 强力驱动 v3.2.0
|
主题 – NexT.Pisces v7.1.1
|
0%