##// END OF EJS Templates
Added Trace<T>.Debug(...) method for debug messages...
cin -
r280:f07be402ab02 v3
parent child
Show More
@@ -1,141 +1,152
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Diagnostics;
4 4 using System.Linq;
5 5 using Implab.Components;
6 6 using Implab.Diagnostics;
7 7 using Implab.ServiceHost.Unity;
8 8 using Implab.Xml;
9 9 using Unity;
10 10 using Unity.Injection;
11 11 using Unity.Registration;
12 12
13 13 namespace Implab.Playground {
14 14
15 15 public class Foo {
16 16
17 17 public class Bar {
18 18
19 19 }
20 20
21 21 public string Name { get; set; }
22 22
23 23 public int IntValue { get; set; }
24 24
25 25 public string StringValue { get; set; }
26 26
27 27 public void AddRange(Foo[] items) {
28 28 Console.WriteLine($"AddRange: Foo[]");
29 29 }
30 30
31 31 }
32 32
33 33 public class FooFactory : IFactory<Foo>, IFactory<Foo.Bar> {
34 34
35 35 public bool UseSsl { get; set; }
36 36
37 37 public string Connection { get; set; }
38 38
39 39 public Foo Create() {
40 40 return new Foo() {
41 41 Name = "AutoFac"
42 42 };
43 43 }
44 44
45 45 Foo.Bar IFactory<Foo.Bar>.Create() {
46 46 return new Foo.Bar();
47 47 }
48 48 }
49 49
50 50 public interface IContainer<T> {
51 51 T Instance { get; set; }
52 52 }
53 53
54 54 public class Container<T> : IContainer<T> {
55 55 public class Bar {
56 56
57 57 }
58 58
59 59 public class Bar<T2> {
60 60 public class Baz {
61 61
62 62 }
63 63
64 64 }
65 65
66 66 public Container() {
67 67
68 68 }
69 69
70 70 public Container(T instance) {
71 71 Instance = instance;
72 72 }
73 73
74 74 public T Instance { get; set; }
75 75
76 76 public void SetInstance(T value) {
77 77 Instance = value;
78 78 }
79 79
80 80 public void AddRange(List<T> items) {
81 81 Console.WriteLine($"AddRange: {typeof(List<T>)}");
82 82 }
83 83
84 84 public void AddRange(T[] items) {
85 85 Console.WriteLine($"AddRange: T[] ofType {typeof(T[])}");
86 86 }
87 87 }
88 88
89 89 public class Program {
90 90
91 91 static void Main(string[] args) {
92 var u1 = new Uri("/some/one");
93
94 Console.WriteLine($"{u1.IsAbsoluteUri}: {u1}");
95
96 var u2 = new Uri(u1, "../../two");
97
98 Console.WriteLine($"{u2.IsAbsoluteUri}: {u2}");
99
100 }
101
102 static void Main2(string[] args) {
92 103 var listener = new SimpleTraceListener(Console.Out);
93 104 var source = Trace<TypeResolver>.TraceSource;
94 105 source.Switch.Level = SourceLevels.All;
95 106 source.Listeners.Add(listener);
96 107
97 108 var stopwatch = new Stopwatch();
98 109 stopwatch.Start();
99 110
100 111 var container = new UnityContainer();
101 112
102 113 Console.WriteLine($"Created: {stopwatch.ElapsedMilliseconds}");
103 114 stopwatch.Restart();
104 115
105 116 container.LoadXmlConfiguration("data/sample.xml");
106 117
107 118 Console.WriteLine($"Loaded: {stopwatch.ElapsedMilliseconds}");
108 119
109 120 stopwatch.Restart();
110 121 var instace1 = container.Resolve<IContainer<string>>();
111 122 Console.WriteLine($"Resolved1: {stopwatch.ElapsedMilliseconds}");
112 123
113 124 stopwatch.Restart();
114 125 var instace2 = container.Resolve<IContainer<Foo>>();
115 126 Console.WriteLine($"Resolved2: {stopwatch.ElapsedMilliseconds}");
116 127
117 128 DisplayContainerRegistrations(container);
118 129 }
119 130
120 131 static void DisplayContainerRegistrations(IUnityContainer theContainer) {
121 132 string regName, regType, mapTo, lifetime;
122 133 Console.WriteLine("Container has {0} Registrations:",
123 134 theContainer.Registrations.Count());
124 135 foreach (ContainerRegistration item in theContainer.Registrations) {
125 136 regType = item.RegisteredType.FullName;
126 137 mapTo = item.MappedToType.FullName;
127 138 regName = item.Name ?? "[default]";
128 139 lifetime = item.LifetimeManager.LifetimeType.Name;
129 140 if (mapTo != regType) {
130 141 mapTo = " -> " + mapTo;
131 142 } else {
132 143 mapTo = string.Empty;
133 144 }
134 145 lifetime = lifetime.Substring(0, lifetime.Length - "LifetimeManager".Length);
135 146 Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
136 147 }
137 148 }
138 149
139 150
140 151 }
141 152 }
@@ -1,111 +1,143
1 1 using System;
2 using System.IO;
2 3 using System.Reflection;
4 using Implab.Diagnostics;
3 5 using Unity;
4 6
5 7 namespace Implab.ServiceHost.Unity {
8 using static Trace<ContainerBuilder>;
9
6 10 public class ContainerBuilder {
7 11
8 12 readonly TypeResolver m_resolver;
9 13
10 14 readonly IUnityContainer m_container;
11 15
12 16 readonly ContainerConfigurationSchema m_schema;
13 17
18 Uri m_location;
19
14 20 public IUnityContainer Container {
15 21 get {
16 22 return m_container;
17 23 }
18 24 }
19 25
20 26 public ContainerBuilder() : this(null, null) {
21 27 }
22 28
23 29 public ContainerBuilder(IUnityContainer container, ContainerConfigurationSchema schema) {
24 30 m_container = container ?? new UnityContainer();
25 31 m_resolver = new TypeResolver();
26 32 m_schema = schema ?? ContainerConfigurationSchema.Default;
27 33 }
28 34
29 35 public Type ResolveType(string typeReference) {
30 36 return string.IsNullOrEmpty(typeReference) ? null : m_resolver.Resolve(typeReference, true);
31 37 }
32 38
33 39 public void Visit(ITypeRegistration registration) {
34 40 Safe.ArgumentNotNull(registration, nameof(registration));
35 41
36 42 var registrationType = registration.GetRegistrationType(this);
37 43 var implementationType = registration.GetImplementationType(this) ?? registrationType;
38 44
39 45 if (registrationType == null)
40 46 throw new Exception($"A type must be specified for the registration {registration.Name}");
41 47
42 48 var builder = new TypeRegistrationBuilder(
43 49 m_resolver,
44 50 registrationType,
45 51 implementationType
46 52 );
47 53
48 54 builder.Lifetime = registration.GetLifetime(this);
49 55
50 56 if (registration.MemberInjections != null) {
51 57 foreach(var member in registration.MemberInjections)
52 58 member.Visit(builder);
53 59 }
54 60
55 61 m_container.RegisterType(
56 62 builder.RegistrationType,
57 63 builder.ImplementationType,
58 64 registration.Name,
59 65 builder.Lifetime,
60 66 builder.Injections
61 67 );
62 68 }
63 69
64 70 public void Visit(IInstanceRegistration registration) {
65 71 Safe.ArgumentNotNull(registration, nameof(registration));
66 72
67 73 var registrationType = registration.GetRegistrationType(this);
68 74
69 75 var builder = new InstanceRegistrationBuilder (
70 76 m_resolver,
71 77 registrationType
72 78 );
73 79
74 80 builder.Lifetime = registration.GetLifetime(this);
75 81
76 82 if (registration.MemberInjections != null) {
77 83 foreach(var member in registration.MemberInjections)
78 84 member.Visit(builder.ValueBuilder);
79 85 }
80 86
81 87 if (builder.RegistrationType == null && builder.ValueBuilder.ValueType == null)
82 88 throw new Exception($"A type must be specified for the registration {registration.Name}");
83 89
84 90 m_container.RegisterInstance(
85 91 builder.RegistrationType ?? builder.ValueBuilder.ValueType,
86 92 registration.Name,
87 93 builder.ValueBuilder.Value,
88 94 builder.Lifetime
89 95 );
90 96 }
91 97
92 98 public void AddNamespace(string ns) {
93 99 m_resolver.AddNamespace(ns);
94 100 }
95 101
96 102 public void AddAssembly(string assembly) {
97 103
98 104 }
99 105
106 /// <summary>
107 /// Includes the confguration. Creates a new <see cref="ContainerBuilder"/>,
108 /// and loads the configuration to it. The created builder will share the
109 /// container and will have its own isolated type resolver.
110 /// </summary>
111 /// <param name="file">A path to configuration relative to the current configuration.</param>
100 112 public void Include(string file) {
101 113 var includeContext = new ContainerBuilder(m_container, m_schema);
102 includeContext.LoadConfig(file);
114
115 if (m_location != null) {
116 var uri = new Uri(m_location, file);
117 includeContext.LoadConfig(uri);
118 } else {
119 includeContext.LoadConfig(file);
120 }
103 121 }
104 122
123 /// <summary>
124 /// Loads a configuration from the specified local file.
125 /// </summary>
126 /// <param name="file">The path to the configuration file.</param>
105 127 public void LoadConfig(string file) {
106 var config = m_schema.LoadFile(file);
128 Safe.ArgumentNotEmpty(file, nameof(file));
129
130 LoadConfig(new Uri(Path.GetFullPath(file)));
131 }
132
133 public void LoadConfig(Uri location) {
134 Safe.ArgumentNotNull(location, nameof(location));
135
136 m_location = location;
137
138 var config = m_schema.LoadConfig(location.ToString());
107 139 config.Visit(this);
108 140 }
109 141
110 142 }
111 143 } No newline at end of file
@@ -1,70 +1,70
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.IO;
4 4 using System.Reflection;
5 5 using System.Xml;
6 6 using System.Xml.Serialization;
7 7 using Implab.Components;
8 8
9 9 namespace Implab.ServiceHost.Unity {
10 10 public class ContainerConfigurationSchema {
11 11
12 12 public static ContainerConfigurationSchema Default { get; private set; } = CreateDefault();
13 13
14 14 readonly LazyAndWeak<XmlSerializer> m_seralizer;
15 15
16 16 readonly XmlAttributeOverrides m_overrides = new XmlAttributeOverrides();
17 17
18 18 readonly XmlAttributes m_containerItems = new XmlAttributes();
19 19
20 20 public XmlSerializer Serializer {
21 21 get {
22 22 return m_seralizer.Value;
23 23 }
24 24 }
25 25
26 26 public ContainerConfigurationSchema() {
27 27 m_overrides.Add(typeof(ContainerElement), nameof(ContainerElement.Items), m_containerItems);
28 28
29 29 m_seralizer = new LazyAndWeak<XmlSerializer>(() => new XmlSerializer(typeof(ContainerElement), m_overrides));
30 30 }
31 31
32 32 public void RegisterContainerElement(Type type, string name) {
33 33 Safe.ArgumentNotNull(type, nameof(type));
34 34 Safe.ArgumentNotEmpty(name, nameof(name));
35 35
36 36 if(!type.IsSubclassOf(typeof(AbstractContainerItem)))
37 37 throw new Exception($"RegisterContainerElement '{name}': {type} must be subclass of {typeof(AbstractContainerItem)}");
38 38
39 39 m_containerItems.XmlElements.Add(
40 40 new XmlElementAttribute(name, type)
41 41 );
42 42 }
43 43
44 44 public void RegisterContainerElement<T>(string name) where T : AbstractContainerItem {
45 45 RegisterContainerElement(typeof(T), name);
46 46 }
47 47
48 public ContainerElement LoadFile(string file) {
49 using (var reader = XmlReader.Create(file)) {
48 public ContainerElement LoadConfig(string uri) {
49 using (var reader = XmlReader.Create(uri)) {
50 50 return (ContainerElement)Serializer.Deserialize(reader);
51 51 }
52 52 }
53 53
54 54 static ContainerConfigurationSchema CreateDefault() {
55 55 var schema = new ContainerConfigurationSchema();
56 56
57 57 schema.RegisterContainerElement<RegisterElement>("register");
58 58 schema.RegisterContainerElement<FactoryElement>("factory");
59 59 schema.RegisterContainerElement<SerializedElement>("serialized");
60 60 schema.RegisterContainerElement<ValueElement>("value");
61 61 schema.RegisterContainerElement<IncludeElement>("include");
62 62 schema.RegisterContainerElement<AssemblyElement>("assembly");
63 63 schema.RegisterContainerElement<NamespaceElement>("namespace");
64 64
65 65 return schema;
66 66 }
67 67
68 68
69 69 }
70 70 } No newline at end of file
@@ -1,43 +1,27
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.ComponentModel;
4 4 using System.Linq;
5 5 using System.Xml.Serialization;
6 6 using Implab.Xml;
7 7 using Unity.Injection;
8 8 using Unity.Lifetime;
9 9 using Unity.Registration;
10 10
11 11 namespace Implab.ServiceHost.Unity {
12 12 /// <summary>
13 13 /// Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ класс для формирования записСй Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅, созволяСт ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ врСмя ΠΆΠΈΠ·Π½ΠΈ для записи
14 14 /// </summary>
15 15 public abstract class RegistrationBuilder {
16 16 public Type RegistrationType {
17 17 get;
18 18 private set;
19 19 }
20 20
21 21 internal LifetimeManager Lifetime { get; set; }
22 22
23 23 protected RegistrationBuilder(Type registrationType) {
24 24 RegistrationType = registrationType;
25 25 }
26
27 internal void Visit(SingletonLifetimeElement simgletonLifetime) {
28 Lifetime = new SingletonLifetimeManager();
29 }
30
31 internal void Visit(ContainerLifetimeElement containerLifetime) {
32 Lifetime = new ContainerControlledLifetimeManager();
33 }
34
35 internal void Visit(HierarchicalLifetimeElement hierarchicalLifetime) {
36 Lifetime = new HierarchicalLifetimeManager();
37 }
38
39 internal void Visist(ContextLifetimeElement contextLifetime) {
40 Lifetime = new PerResolveLifetimeManager();
41 }
42 26 }
43 27 } No newline at end of file
@@ -1,132 +1,144
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Diagnostics;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading;
7 7 using System.Threading.Tasks;
8 8
9 9 namespace Implab.Diagnostics {
10 10 public static class Trace<T> {
11 11
12 12 public static TraceSource TraceSource { get; } = new TraceSource(typeof(T).Name);
13 13
14 14 #if NETFX_TRACE_BUG
15 15 readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>();
16 16 #endif
17 17
18 18 /// <summary>
19 19 /// Starts the logical operation nested to the current operation nested to the current one.
20 20 /// </summary>
21 21 public static void StartLogicalOperation() {
22 22 Trace.CorrelationManager.StartLogicalOperation();
23 23
24 24 }
25 25
26 26 /// <summary>
27 27 /// Starts the logical operation with the specified name, this name is usefull in logs.
28 28 /// </summary>
29 29 /// <param name="name">Name.</param>
30 30 #if NETFX_TRACE_BUG
31 31 public static void StartLogicalOperation(object name) {
32 32 m_currentOperation.Value = name;
33 33 Trace.CorrelationManager.StartLogicalOperation(name);
34 34 }
35 35 #else
36 36 public static void StartLogicalOperation(object name) {
37 37 Trace.CorrelationManager.StartLogicalOperation(name);
38 38 }
39 39 #endif
40 40
41 41 /// <summary>
42 42 /// Ends the logical operation and restores the previous one.
43 43 /// </summary>
44 44 public static void StopLogicalOperation() {
45 45 Trace.CorrelationManager.StopLogicalOperation();
46 46 }
47 47
48 48 /// <summary>
49 /// Writes a debug message.
50 /// </summary>
51 /// <param name="format">Format.</param>
52 /// <param name="arguments">Arguments.</param>
53 [Conditional("DEBUG")]
54 public static void Debug(string format, params object[] arguments) {
55
56 }
57
58 /// <summary>
49 59 /// Writes an informational message.
50 60 /// </summary>
51 61 /// <param name="format">Format.</param>
52 62 /// <param name="arguments">Arguments.</param>
53 63 [Conditional("TRACE")]
54 64 public static void Log(string format, params object[] arguments) {
55 65 TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
56 66 }
57 67
58 68 /// <summary>
59 69 /// Writes a warning message.
60 70 /// </summary>
61 71 /// <param name="format">Format.</param>
62 72 /// <param name="arguments">Arguments.</param>
63 [Conditional("TRACE")]
64 73 public static void Warn(string format, params object[] arguments) {
65 74 TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments);
66 75 }
67 76
68 [Conditional("TRACE")]
77 /// <summary>
78 /// Writes a error message.
79 /// </summary>
80 /// <param name="format">Format.</param>
81 /// <param name="arguments">Arguments.</param>
69 82 public static void Error(string format, params object[] arguments) {
70 83 TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments);
71 84 }
72 85
73 [Conditional("TRACE")]
74 86 public static void Error(Exception err) {
75 87 TraceSource.TraceData(TraceEventType.Error, 0, err);
76 88 }
77 89
78 90 /// <summary>
79 91 /// This method save the current activity, and transfers to the specified activity,
80 92 /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new
81 93 /// activity.
82 94 /// </summary>
83 95 /// <param name="activityName">The name of the new activity/</param>
84 96 /// <param name="activityId">The identifier of the activity to which
85 97 /// the control will be transferred</param>
86 98 /// <returns>A scope of the new activity, dispose it to transfer
87 99 /// the control back to the original activity.</returns>
88 100 public static ActivityScope TransferActivity(string activityName, Guid activityId) {
89 101 var prev = Trace.CorrelationManager.ActivityId;
90 102
91 103 TraceSource.TraceTransfer(0, "Transfer", activityId);
92 104 Trace.CorrelationManager.ActivityId = activityId;
93 105 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
94 106
95 107 return new ActivityScope(TraceSource, prev, 0, activityName);
96 108 }
97 109
98 110 /// <summary>
99 111 /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the
100 112 /// activity.
101 113 /// </summary>
102 114 /// <param name="activityName">The name of the activity to start</param>
103 115 /// <returns>A scope of the new activity, dispose it to emit
104 116 /// <see cref="TraceEventType.Stop"/> for the current activity.</returns>
105 117 public static ActivityScope StartActivity(string activityName) {
106 118 if (Trace.CorrelationManager.ActivityId == Guid.Empty)
107 119 Trace.CorrelationManager.ActivityId = Guid.NewGuid();
108 120
109 121 var prev = Trace.CorrelationManager.ActivityId;
110 122
111 123 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
112 124 return new ActivityScope(TraceSource, prev, 0, activityName);
113 125 }
114 126
115 127 /// <summary>
116 128 /// Creates new <see cref="LogicalOperation(string)"/> and calls
117 129 /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/>
118 130 /// passing the created operation as identity. Calls
119 131 /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/>
120 132 /// to notify listeners on operation start.
121 133 /// </summary>
122 134 /// <param name="name">The name of the logical operation.</param>
123 135 /// <returns>Logical operation scope, disposing it will stop
124 136 /// logical operation and notify trace listeners.</returns>
125 137 public static LogicalOperationScope LogicalOperation(string name) {
126 138 var operation = new LogicalOperation(name);
127 139 TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation);
128 140 StartLogicalOperation(operation);
129 141 return new LogicalOperationScope(TraceSource, operation);
130 142 }
131 143 }
132 144 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now