-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathImplementFieldAccessorTask.cs
91 lines (82 loc) · 2.82 KB
/
ImplementFieldAccessorTask.cs
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright (C) 2013 Xtensive LLC.
// All rights reserved.
// For conditions of distribution and use, see license.
// Created by: Denis Krjuchkov
// Created: 2013.08.19
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Xtensive.Orm.Weaver.Tasks
{
internal sealed class ImplementFieldAccessorTask : WeavingTask
{
private readonly TypeDefinition type;
private readonly PropertyDefinition property;
private readonly int persistentIndex;
private readonly AccessorKind kind;
public override ActionResult Execute(ProcessorContext context)
{
switch (kind) {
case AccessorKind.Getter:
ImplementGetter(context);
break;
case AccessorKind.Setter:
ImplementSetter(context);
break;
default:
throw new ArgumentOutOfRangeException();
}
return ActionResult.Success;
}
private void ImplementSetter(ProcessorContext context)
{
var accessor = GetAccessor(context,
context.References.PersistentSetters, context.References.PersistentSetterDefinition);
var body = property.SetMethod.Body;
body.Instructions.Clear();
var il = body.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, persistentIndex);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, accessor);
il.Emit(OpCodes.Ret);
}
private void ImplementGetter(ProcessorContext context)
{
var accessor = GetAccessor(context,
context.References.PersistentGetters, context.References.PersistentGetterDefinition);
var body = property.GetMethod.Body;
body.Instructions.Clear();
var il = body.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, persistentIndex);
il.Emit(OpCodes.Call, accessor);
il.Emit(OpCodes.Ret);
}
private MethodReference GetAccessor(ProcessorContext context,
IDictionary<TypeIdentity, MethodReference> registry, MethodReference definition)
{
var identity = new TypeIdentity(property.PropertyType);
MethodReference result;
if (!registry.TryGetValue(identity, out result)) {
var accessor = new GenericInstanceMethod(definition);
accessor.GenericArguments.Add(property.PropertyType);
result = context.TargetModule.ImportReference(accessor);
registry.Add(identity, result);
}
return result;
}
public ImplementFieldAccessorTask(AccessorKind kind, TypeDefinition type, PropertyDefinition property, int persistentIndex)
{
if (type==null)
throw new ArgumentNullException("type");
if (property==null)
throw new ArgumentNullException("property");
this.kind = kind;
this.type = type;
this.property = property;
this.persistentIndex = persistentIndex;
}
}
}