Error binding to target method in C#3.0 - reflection

I am trying to hook Up a Delegate Using Reflection. This is what I have done so far
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Data;
using System.Threading;
using System.IO;
using System.Reflection;
using System.Windows;
namespace ChartHelper
{
public class ICChartHelper
{
public void RefreshChart()
{
try
{
Assembly myobj = Assembly.LoadFrom(#"C:\sample.dll");
foreach (Type mytype in myobj.GetTypes())
{
if (mytype.IsClass == true)
{
if (mytype.FullName.EndsWith("." + "ICAutomationProxy"))
{
// create an instance of the object
object ClassObj = Activator.CreateInstance(mytype);
// var eventTypes = mytype.GetEvents();
EventInfo evClick = mytype.GetEvent("OnRefreshCompleted");
Type tDelegate = evClick.EventHandlerType;
MethodInfo miHandler =
typeof(ChartHelper.ICChartHelper)
.GetMethod("RefreshApplication",
BindingFlags.NonPublic | BindingFlags.Instance);
Delegate d = Delegate.CreateDelegate(tDelegate,typeof(ChartHelper.ICChartHelper), miHandler);
MethodInfo addHandler = evClick.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(ClassObj, addHandlerArgs);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private void RefreshApplication(Object sender, EventArgs e)
{
MessageBox.Show("Bingo");
}
But in the
Delegate d = Delegate.CreateDelegate(tDelegate,typeof(ChartHelper.ICChartHelper), miHandler);
line, I am encountering the error Error binding to target method
I have also found the discusion here and tried to solve the same but with no luck.
I need help to understand what wrong I am doing?
Thanks

Your method is an instance method, so you need to use an overload of CreateDelegate which takes the target of the delegate, and pass in an instance of the declaring type. For example:
Delegate d = Delegate.CreateDelegate(tDelegate, new ICChartHelper(), miHandler);
Note that you don't need to call GetAddMethod on the EventInfo and invoke that using reflection - you can just use EventInfo.AddEventHandler.

Related

Read XML and get data in ASP.net Web application

I need to find coSpaces total="3" value from the below XML in ASP.net C#. Please help me with the xmlreader code. I have seen other tutorial where I can find element value but not this type.
Thanks,
<?xml version="1.0"?>
<coSpaces total="3">
<coSpace id="0">
<name>A</name>
<autoGenerated>false</autoGenerated>
</coSpace>
<coSpace id="2">
<name>B</name>
<autoGenerated>false</autoGenerated>
</coSpace>
<coSpace id="4">
<name>C</name>
<autoGenerated>false</autoGenerated>
</coSpace>`
</coSpaces>
You can get total in this way:
private static string GetTotal()
{
var document = new XmlDocument();
using (var file = new FileStream("file.xml", FileMode.Open))
{
using (var reader = XmlReader.Create(file))
{
while (reader.Read())
{
if (reader.IsStartElement())
{
var attr = reader["total"];
return attr;
}
}
}
}
return null;
}
Taking a minute to learn XPath, and the 2 methods that use it (SelectSingleNode, and SelectNodes) will really help in a lot of situations.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace testconsole
{
class Program
{
public static string strFileName = "c:\\temp\\test.xml";
static void Main(string[] args) {
XmlDocument xml = new XmlDocument();
xml.Load(strFileName);
XmlElement ndMatch = (XmlElement) xml.SelectSingleNode("//coSpaces[#total=3]");
if (ndMatch != null) {
foreach (XmlElement ndCoSpace in ndMatch.SelectNodes("coSpace")) {
Console.Write(ndCoSpace.GetAttribute("id"));
}
} else {
Console.Write("Not found in " + strFileName);
}
}
}
}

Non-Null Domain Name Breaks Page

We had CefSharp calling a project deployed on IIS. That worked. And a cookie I need for the third party library is loaded successfully.
Now we want CefSharp to load the same html and third party library through disk, bypassing IIS. Files are loading and running complete with functioning javascript, however the third party library requires a "domain name" to match the one associated with the license.
I need my domain name to match the one on my license which was generated with domain=localhost. But once I specify a domain name, the page, including the license checker, doesn't load.
This is a related problem. A cookie I need to load loads succesfully when I use csharp to call the IIS project, but fails when I open up the html project from disk. For reference, static void FrameLoaded is the same cookie loading procedure used in both versions of my project.
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MinRepExample2
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
namespace MinRepExample2
{
public partial class Form1 : Form
{
private ChromiumWebBrowser browser;
public Form1()
{
InitializeComponent();
try
{
string siteURL = "";
string FileBase = #"c:\users\romero.ryan\documents\visual studio 2015\Projects\MinRepExample2";
string CacheDir = FileBase+#"\Cef2";
// CefSettings to temporarily reduce security
CefSettings MySettings = new CefSettings();
MySettings.CachePath = CacheDir;
MySettings.CefCommandLineArgs.Add("enable-media-stream", "enable-media-stream");
MySettings.CefCommandLineArgs.Add("allow-file-access-from-files", "allow-file-access-from-files");
MySettings.CefCommandLineArgs.Add("disable-web-security", "disable-web-security");
MySettings.JavascriptFlags = "--expose-wasm";
// Browser Settings
BrowserSettings browserSettings = new BrowserSettings();
browserSettings.FileAccessFromFileUrls = CefState.Enabled;
browserSettings.LocalStorage = CefState.Enabled;
browserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
browserSettings.WebSecurity = CefState.Disabled;
// Custom Scheme Registration
MySettings.RegisterScheme(new CefCustomScheme
{
SchemeName = MySchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new MySchemeHandlerFactory(),
IsFetchEnabled = true,
IsLocal = false,
IsCorsEnabled = true,
IsSecure = true,
//DomainName= #"\Users\romero.ryan"
DomainName = "localhost"
});
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
if (!Cef.IsInitialized)
{
Cef.Initialize(MySettings);
}
//string fName = #"C:\Users\romero.ryan\Documents\Visual Studio 2015\Projects\WinHostScandit1\WebHostOnDisk\CefPrimeFiles";
//c:\users\romero.ryan\documents\visual studio 2015\Projects\MinRepExample2\TestSite.html
browser = new ChromiumWebBrowser(#"fileProtocol:\\" + FileBase + "\\TestSite.html");
browser.BrowserSettings = browserSettings;
browser.Dock = DockStyle.Fill;
browser.Name = "browser";
browser.LoadingStateChanged += FrameLoaded;
this.Controls.Add(browser);
}
catch (Exception ex)
{
throw ex;
}
}
public void FrameLoaded(object sender, LoadingStateChangedEventArgs e)
{
//ChromiumWebBrowser ans = (ChromiumWebBrowser)Controls.Find("browser", false).First();
if (!e.IsLoading)
{
// CefSharp specific Cookie manipulation to register app as single device used with Scandit Library.
// ADD Cookie in C# code. Also adding in javascript code
var cookman = browser.GetCookieManager();
string[] schemes = { "fileProtocol", "fileprotocol", "fileprotocol:", "fileProtocol:" };
cookman.SetSupportedSchemes(schemes, true);
CefSharp.Cookie cook1 = new CefSharp.Cookie();
cook1.Domain = "localhost";
cook1.Name = "scandit-device-id";
cook1.Value = "ffaf4f340998d137fc260d563004eabcd388e90f";
cook1.Path = "/scanditpage";
cook1.Expires = new DateTime(2029, 6, 17);
// cookman.SetCookieAsync(ConfigurationManager.AppSettings["ScanditURL"], cook1);
var respcook = cookman.SetCookieAsync("http://localhost/scanditpage/ScanditTest.html", cook1);
bool cookieSet = cookman.SetCookie("http://localhost/scanditpage/ScanditTest.html", cook1);
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
//cookman.SetCookie
// Adding Test cookie
browser.ExecuteScriptAsync("TestAddCookie()");
// Launches Dev tools for Debugging Purposes.
browser.ShowDevTools();
}
}
}
}
MySchemeHandler.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
using System.IO;
namespace MinRepExample2
{
public class MySchemeHandler : ResourceHandler
{
public const string SchemeName = "fileProtocol";
private string folderPath;
public MySchemeHandler()
{
folderPath = "";
}
public override CefSharp.CefReturnValue ProcessRequestAsync(IRequest request, ICallback callback)
{
var uri = new Uri(request.Url);
string fileName = uri.LocalPath;
var requestedFilePath = "C:/" + fileName;
string bFileName = "";
bFileName = requestedFilePath;
if (File.Exists(bFileName))
{
byte[] bytes = File.ReadAllBytes(bFileName);
Stream = new MemoryStream(bytes);
var fileExtension = Path.GetExtension(bFileName);
MimeType = GetMimeType(fileExtension);
return CefReturnValue.Continue;
//return true;
}
else
{
throw new FileNotFoundException();
}
callback.Dispose();
return CefReturnValue.Continue;
}
}
}
MySchemeHandlerFactory:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
namespace MinRepExample2
{
public class MySchemeHandlerFactory: ISchemeHandlerFactory
{
public const string SchemeName = "fileProtocol";
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
return new MySchemeHandler();
}
}
}
Testing HTML:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Test Site for CefSharp Cookies</title>
<script type="text/javascript">
function AddCookie(name, value) {
// Add cookie as name value pair.
var newcookie = name + "=" + value + ";";
document.cookie=newcookie
}
function TestAddCookie() {
// Add specific cookie. Called from executescript in FrameLoaded method
AddCookie("name", "everlast");
}
function ButtonCookie() {
//Adds cookie by button click, then displays all available cookies.
AddCookie("button", "clicked");
var decodedCookie = decodeURIComponent(document.cookie);
alert(decodedCookie);
}
</script>
</head>
<body>
<div>Hello, World!</div>
<button onclick="ButtonCookie();">Add Cookie</button>
</body>
</html>
I figured it out from advice from amaitland and this answer: Simple Custom Scheme.
CefSettings allows you to set permissions like allowing CORS and Fetch for loading WASM files. CefSettings is also used for registering custom scheme handlers. Some schemes might need special permissions to load dependent javascript libraries. Permissions associated with this variable must be set before calling Cef.Initialize. Cef.Initialize should not be called after new ChromiumWebBrowser();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using CefSharp.SchemeHandler;
namespace EpmsMobileWF.ScanditWebForm
{
public partial class ScanditPopupForm : Form
{
public static ScanditPopupConfig scanditConfigs;
public static JSObj1 mess;
public ChromiumWebBrowser browser;
public ScanditPopupForm(TextBox inForm)
{
InitializeComponent();
InitScanner();
mess = new JSObj1(inForm, this);
}
public void InitScanner()
{
scanditConfigs = new ScanditPopupConfig();
var settings = new CefSettings();
FolderSchemeHandlerFactory newFac = new FolderSchemeHandlerFactory(scanditConfigs.HTMLRootFolder,null, scanditConfigs.DomainName, "ScanditTest.html");
CefCustomScheme ScanditScheme = new CefCustomScheme
{
SchemeName = "http",
DomainName = scanditConfigs.DomainName,
SchemeHandlerFactory = newFac,
};
ScanditScheme.IsCorsEnabled = true;
ScanditScheme.IsFetchEnabled = true;
ScanditScheme.IsLocal = true;
ScanditScheme.IsStandard = true;
settings.CachePath = scanditConfigs.ScanditCacheDirectory;
settings.CefCommandLineArgs.Add("enable-media-stream", "enable-media-stream");
settings.CefCommandLineArgs.Add("allow-file-access-from-files", "allow-file-access-from-files");
settings.PersistSessionCookies = true;
settings.JavascriptFlags = "--expose-wasm";
settings.RegisterScheme(ScanditScheme);
Cef.Initialize(settings);
browser = new ChromiumWebBrowser(scanditConfigs.ScanditURL);
this.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
}
}
}

Prevent Inserting same combination of Component and template :

In a page when we will click the component Presentation tab we can see the component and template listed there.On clicking of Insert button just below that, it will open another window "Insert component presentation" there also we will have Insert and close button.So now what i need to do While inserting i need to check whether the combination of selected Component and Template is already present there on page or not. If yes then it should prevent inserting the same with a popup like "this combination is already present, select other componet".
Any idea how can i proceed. How can i trigger a Javascript on the Insert button?
EDIT:
When i am subscrbing it to Page i am getting erro.My code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using Tridion.ContentManager.Extensibility.Events;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.ContentManagement;
using System.IO;
using System.Windows.Forms;
namespace MyEventHandlers
{
[TcmExtension("MyEventHandlerExtension")]
public class MyEventHandler : TcmExtension
{
public MyEventHandler()
{
Subscribe();
}
public void Subscribe()
{
EventSystem.Subscribe<Page, SaveEventArgs>(SaveBtnInitiated, EventPhases.Initiated);
}
private void SaveBtnInitiated(Page subject, SaveEventArgs args, EventPhases phase)
{
try
{
List<string> allcplist = new List<string>();
List<string> allcplist = new List<string>();
foreach (ComponentPresentation cp in subject.ComponentPresentations)
{
allcplist.Add(cp.Component.Id + "," + cp.ComponentTemplate.Id);
}
List<string> uniquecplist = allcplist.Distinct().ToList();
if (allcplist.Count != uniquecplist.Count)
{
subject.Checkin(false);
throw new Exception("Page has duplicate component presentation");
}
catch(Exception)
{
}
}
You can implement this in an event handler that is subscribed to the Page Save event and the Initiated phase. When there is a duplicate Component Presentation you can cancel the Save by throwing an exception. The message will be shown in the Message Center in the TCM Explorer.
Why are you subscribing to the Component? I think it should be the Page. Then you can walk through the ComponentPresentations property.
Code to go through the Component Presentations and throw an exception when duplicate presentations are found:
foreach (var cpA in subject.ComponentPresentations)
{
if (subject.ComponentPresentations.Where(cpB => ComponentPresentationsAreEqual(cpA, cpB)).ToList().Count() > 2)
{
throw new DuplicateComponentPresentationsEmbeddedOnPageException();
}
}
And the function to include cpB in the list when it is equal to cpA:
function ComponentPresentationsAreEqual(ComponentPresentation cpA, ComponentPresentation cpB)
{
return cpA.Component.Id == cpB.Component.Id && cpA.ComponentTemplate.Id == cpB.ComponentTemplate.Id;
}
I got my Result with this code Thanks to #Arjen Stobbe
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using Tridion.ContentManager.Extensibility.Events;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.ContentManagement;
using System.IO;
using System.Windows.Forms;
namespace MyEventHandlers
{
[TcmExtension("MyEventHandlerExtension")]
public class MyEventHandler : TcmExtension
{
public MyEventHandler()
{
Subscribe();
}
public void Subscribe()
{
EventSystem.Subscribe<Page, SaveEventArgs>(SaveBtnInitiated, EventPhases.Initiated);
}
private void SaveBtnInitiated(Page subject, SaveEventArgs args, EventPhases phase)
{
try
{
List<string> allcplist = new List<string>();
List<string> allcplist = new List<string>();
foreach (ComponentPresentation cp in subject.ComponentPresentations)
{
allcplist.Add(cp.Component.Id + "," + cp.ComponentTemplate.Id);
}
List<string> uniquecplist = allcplist.Distinct().ToList();
if (allcplist.Count != uniquecplist.Count)
{
subject.Save(false);
throw new Exception("Page has duplicate component presentation");
}
catch(Exception)
{
}
}
But i am not deleting the duplicate CP present on the page. Do i need to add,
for each()
inside
if (allcplist.Count != uniquecplist.Count)
{
}

Recursive function to going through each embedded schema field in a schema to reach a leaf data field

I have a schema in Tridion which have embedded schema fields which may further have embedded fields in there.
I want to reach final leaf field so that I can assign some value to it. For that I want to write recursive function which loop through each and every field until it reaches a final field.
I am implementing using the Core Service in SDL Tridion 2011
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ServiceModel;
using System.Net;
using System.Xml;
using Tridion.ContentManager.CoreService.Client;
using System.Text;
using Tridion.ContentManager.CoreService;
using System.ServiceModel.Channels;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Data.OleDb;
using System.Data;
using System.Configuration;
namespace Loading_Utility
{
public partial class TST : System.Web.UI.Page
{
Fields obj = new Fields();
protected void Page_Load(object sender, EventArgs e)
{
using (ChannelFactory<ISessionAwareCoreService> factory =
new ChannelFactory<ISessionAwareCoreService>("wsHttp_2011"))
{
ISessionAwareCoreService client = factory.CreateChannel();
var schemaFields = client.ReadSchemaFields("tcm:202-2242-8", true, new ReadOptions());
ComponentData component = (ComponentData)client.GetDefaultData(ItemType.Component, "tcm:202-638-2");
var fields = Fields.ForContentOf(schemaFields);
component.Schema.IdRef="tcm:202-2242-8";
}
}
public void fieldRecursion(Field field)
{
//var getFields = fields;
if (field.GetType() == typeof(EmbeddedSchemaFieldDefinitionData))
{
// code for checking further if field is embedded or not
//Field newField = field.GetSubFields().GetFieldElements( new ItemFieldDefinitionData() as Field)
//fieldRecursion(recursiveField);
}
//string fieldName = recursiveField.Name;
//fields[fieldName] = "HI";
}
}
}
Whilst I don't have the solution you are looking for, I see you're using the core service, personally I prefer to get hold of the Component XML (Component.Content) and parse/manipulate it as I need. Perhaps if you can paste the XML here I can drop it into one of my sample core service projects and send you a solution back?
In the event that doesn't help you, i've had a look at the api, and this should help you get going in the right path. Perhaps once you have a solution you could paste it here?
public void RecurseEmbeddedFields(SchemaFieldsData schemaFields)
{
foreach (ItemFieldDefinitionData field in schemaFields.Fields)
{
if (field.GetType() == typeof(EmbeddedSchemaFieldDefinitionData))
{
// check if this field contains more embedded fields
// if it does recurse
}
}
}
OK, I felt a bit guilty about not helping, but I still stand by my view that this is not a Tridion-related question and that you should try getting some more experience with general development practices.
Here's an example of how to load the Component's content, then read it recursively using Xml:
Xml of the component:
<Content xmlns="uuid:02395f72-acef-44e8-9c35-ff8c9f380251">
<EmbeddedSchema1>
<SomeField>Hello</SomeField>
<EmbeddedSchema2>
<ATextField>There</ATextField>
</EmbeddedSchema2>
</EmbeddedSchema1>
</Content>
Core Service code:
static void Main(string[] args)
{
SessionAwareCoreServiceClient client = new SessionAwareCoreServiceClient("wsHttp_2011");
ReadOptions readOptions = new ReadOptions();
ComponentData component = (ComponentData)client.Read("tcm:5-3234", readOptions);
Console.WriteLine("Find fields recursively");
XmlDocument content = new XmlDocument();
content.LoadXml(component.Content);
SchemaData schema = (SchemaData)client.Read(component.Schema.IdRef, readOptions);
XmlNamespaceManager ns = new XmlNamespaceManager(new NameTable());
ns.AddNamespace("content", schema.NamespaceUri);
foreach (XmlElement node in content.SelectNodes("content:*", ns))
{
ReadContentRecursively(node, ns);
}
client.Close();
}
private static void ReadContentRecursively(XmlElement node, XmlNamespaceManager ns)
{
if(!string.IsNullOrEmpty(node.InnerText))
{
foreach (XmlNode innerNode in node)
{
if(innerNode is XmlText)
{
Console.WriteLine("Node " + node.Name + " with value \"" + innerNode.Value + "\"");
}
}
}
if(node.SelectNodes("content:*", ns).Count > 0)
{
foreach (XmlElement childNode in node.SelectNodes("content:*", ns))
{
Console.WriteLine("Found Field: " + childNode.Name);
ReadContentRecursively(childNode, ns);
}
}
}
Notice how ReadContentRecursively calls itself?
Hope this helps.

Unity.BuildUp unable to disambiguate

I have a class with two constructors, both constructors have one parameter. Due to restrictions not worth explaining I cannot alter the constructors or use a descendent class.
I can't use unity to create instances of this class because Unity sees 2 constructors with the same number of parameters and complains that it doesn't know which to use, which is fair enough. So instead I create the instance myself and then try to use UnityContainer.BuildUp()
var result = constructorInfo.Invoke(new object[] { content });
UnitContainer.BuildUp(result);
The above code does not set any of my [Dependency] properties nor does it call an [InjectionMethod] if I use that instead.
var result = constructorInfo.Invoke(new object[] { content });
UnitContainer.BuildUp(typeOfObject, result);
This throws another exception about ambiguous constructors, even though I am not asking it to construct the instance.
Does anyone have any ideas?
Here is an example app
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using System.Reflection;
namespace ConsoleApplication7
{
public interface IConstructorType1 { }
public interface IConstructorType2 { }
public interface INeedThisDependency { }
public class NeedThisDependency : INeedThisDependency { }
public class MyDomainObject
{
public MyDomainObject(IConstructorType1 constructorType1) { }
public MyDomainObject(IConstructorType2 constructorType2) { }
[Dependency]
public INeedThisDependency Needed { get; set; }
}
class Program
{
static void Main(string[] args)
{
IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<INeedThisDependency, NeedThisDependency>();
//Try with type 1 constructor
ConstructorInfo constructorInfo1 = typeof(MyDomainObject).GetConstructor(new Type[] { typeof(IConstructorType1) });
MyDomainObject instance1 = CreateTheInstance(unityContainer, typeof(MyDomainObject), constructorInfo1, null);
//Try with type 2 constructor
ConstructorInfo constructorInfo2 = typeof(MyDomainObject).GetConstructor(new Type[] { typeof(IConstructorType2) });
MyDomainObject instance2 = CreateTheInstance(unityContainer, typeof(MyDomainObject), constructorInfo2, null);
}
//This is the only point I have any influence over what happens
//So this is the only place I get to change the code.
static MyDomainObject CreateTheInstance(IUnityContainer unityContainer, Type type, ConstructorInfo constructorInfo, object parameters)
{
var result = (MyDomainObject)constructorInfo.Invoke(new object[] { parameters });
//This will throw an ambiguous constructor exception,
//even though I am not asking it to construct anything
unityContainer.BuildUp(type, result);
//This will not build up dependencies
unityContainer.BuildUp(result);
if (result.Needed == null)
throw new NullReferenceException("Needed");
return result;
}
}
}
It's a bug in BuildUp, unfortunately.
Instead of calling BuildUp call this CallInjectionMethod helper.
public static class UnityContainerHelper
{
public static void CallInjectionMethod(this IUnityContainer unityContainer, object instance, params ResolverOverride[] overrides)
{
if (instance == null)
throw new ArgumentNullException("Instance");
var injectionMethodInfo = instance.GetType().GetMethods().Where(x => x.GetCustomAttributes(typeof(InjectionMethodAttribute), true).Any()).SingleOrDefault();
if (injectionMethodInfo == null)
return;
var parameters = injectionMethodInfo.GetParameters();
if (parameters.Length == 0)
return;
var dependencies = new object[parameters.Length];
int index = 0;
foreach (Type parameterType in parameters.Select(x => x.ParameterType))
{
dependencies[index] = unityContainer.Resolve(parameterType, overrides);
index++;
}
injectionMethodInfo.Invoke(instance, dependencies);
}
}

Resources