I have an event like this:
private void btnStartAnalysis_Click(object sender, EventArgs e)
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
string[] arrArgs = { objConnectionString.ConnectionString };
//Checks for the selectedItem in the cmbOpearions dropdown and make call to appropriate functions.
string assemblyName = cmbOperations.SelectedValue.ToString();
Assembly assembly = Assembly.LoadFrom(assemblyName);
Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
IMFDBAnalyserPlugin analyser = (IMFDBAnalyserPlugin) Activator.CreateInstance(localType);
string response = analyser.RunAnalysis(objConnectionString.ConnectionString);
//show the response of the the function call
txtPluginResponse.Text = response;
}
I want this line to be dynamic:
Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
where PrimaryKeyChecker is a namespace and another PrimaryKeyChecker is the class.
But I want to create other namespaces and classes, so is there any way to call them dynamically and load them in the combobox like this.
public void SetOperationDropDown()
{
cmbOperations.DataSource = PluginManager.GetAllPlugins();
if(cmbOperations.Items.Count > 0)
{
cmbOperations.SelectedItem = cmbOperations.Items[0];
}
}
You've almost answered your own question! Assuming you have a list of plugins, configured in a config file or whatnot, then your PluginManager can load up the Types from the assembly using code similar to:
Type analyserType = typeof(IMFDBAnalyserPlugin);
foreach(Type t in assembly.GetTypes()) {
if(t.IsSubtypeOf(analyserType) {
plugins.Add((IMFDBAnalyserPlugin) Activator.CreateInstance(t));
}
}
If you do not have a list of plugins, then you can either scan a directory and do the same thing as above. You could also consider using a plugin framework architecture like MEF and it does a lot of that work for you and discovers the assemblies and plugins at runtime.
I think the answer of Tom can help you populate a list of plugins. Bind them to the combobox where you put the text / description to the Type name and bind the value of combo-items to the actual Type declaration. And you asked for the event to be "Dynamic"...Do you probably mean generic??? Then i would advice to refactor the code in the click_event to a private method, to be able to call it from other "places" as well. Then in the click_event you retrieve the selected Plugin Type from the currently selected item a provide this in the generic function call to RunAnalysis like this:
private void btnStartAnalysis_Click(object sender, EventArgs e)
{
if(cmbOperations.SelectedItem != null)
RunAnalysis<cmbOperations.SelectedItem.Value>();
}
private void RunAnalysis<T>()
{
//Checks for the selectedItem in the cmbOpearions dropdown and make call to appropriate functions.
//string assemblyName = cmbOperations.SelectedValue.ToString();
//Assembly assembly = Assembly.LoadFrom(assemblyName);
//Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
IMFDBAnalyserPlugin analyser =
(IMFDBAnalyserPlugin) Activator.CreateInstance(T);
string response = analyser.RunAnalysis(objConnectionString.ConnectionString);
//show the response of the the function call
txtPluginResponse.Text = response;
}
Another way could be to just use a parameter for the Type currently selected. Hope this helps you out or to bring you to new ideas towards a solution.
Related
i have opened solidworks assembly (swDocumentTypes_e.swDocASSEMBLY) using C# and i have iterated through all the features in order to get all the Sketchs called 'ISO/XXX' under each part of the assembly, here is the code
public void openFile(string skeletonFilePath)
{
object[] Features = null;
int i = 0;
string FeatType = null;[1]
string FeatTypeName = null;
if (string.IsNullOrWhiteSpace(skeletonFilePath)) { return; }
ModelDoc2 model = _sldWorks.OpenDoc("C:PATH/fileName.SLDASM", (int)swDocumentTypes_e.swDocASSEMBLY);
Feature swFeat = default(Feature);
SelectionMgr swSelMgr = default(SelectionMgr);
swSelMgr = (SelectionMgr)model.SelectionManager;
swFeat = (Feature)model.FirstFeature();
while ((swFeat != null))
{
FeatType = swFeat.Name;
FeatTypeName = swFeat.GetTypeName2();
if ((FeatTypeName == "Reference")
{
Debug.Print(" Name of feature: " + swFeat.Name);
Debug.Print(" Type of feature: " + swFeat.GetTypeName2());
}
swFeat = (Feature)swFeat.GetNextFeature();
}
}
the problem:
each time i try to extract the items under the feature (of one part) i got an exception, i have to tried these ways:
swFeat.GetDefinition() // i've got null exception
swFeat.GetSpecificFeature2() // i've got dynamic value which i don't know the class i need to cast with
var childs = (Object[])swFeatSupport.GetChildren(); // i've got only to constraints under the part
example of project
Your code is only iterating over top level features. You can use IFeature::GetFirstSubFeature() and IFeature::GetNextSubFeature to get sub feature. Make this function recursive so it will iterate over all features, regardless of how many levels deep they are. Another layer you need to consider is the components - you need to iterate over components in an assembly first if you need feature data in the context of individual parts.
Here's an example from the Solidworks API documentation. Its poorly written (IMO) but it will guide you in the right direction.
I think I've come across a bug in the CreateFolder command in the Reportingservices2010 SOAP API
The test scenario is I'm trying to create a folder (named Sales Dashboard) in the same Parent folder (lets say Sales) as a report also named Sales Dashboard.
The command completed with the "AlreadyExists" Exception when the folder does not already exist. It looks like the method isn't checking the catalog item type.
Here's my code:
public static void createFolders(string targetURL, string folderName, string parentPath, string description, string visible)
{
//Build Authentication
ReportingService2010 rs = new ReportingService2010();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.Url = targetURL;
//Declare properties
Property descriptionProp = new Property();
Property visibleProp = new Property();
Property[] props = new Property[2];
descriptionProp.Name = "Description";
descriptionProp.Value = description;
visibleProp.Name = "Visible";
visibleProp.Value = visible;
props[0] = descriptionProp;
props[1] = visibleProp;
try
{
rs.CreateFolder(folderName, parentPath, props);
}
catch(Exception ex)
{
if(ex.Message.Contains("AlreadyExists"))
{
//do nothing?
}
else
{
throw;
}
}
}
I wanted to see if I could contribute a fix but there's no GitHub repo for the C# SSRS stuff. Any thought's on a workaround?
The API is returning the correct error since this is a restriction of Reporting Services in general: items within the same folder must have unique names (regardless of item type).
I have WinForm called Form1 and there are Button1, MemoEdit1 and 2 TextBoxes named TextBox1 and TextBox2. At runtime user should be able write C# code in MemoEdit1 in order to manipulate the TextBox controls. F.e: at runtime user typed into MemoEdit1 simple code like: TextBox2.Text = "Hello" + TextBox1.Text;
So, when I click on Button1, I need to compile and execute the code.
Question may sound so simple as I am a newbie in compiling/executing code during runtime in C#.
Could you pls, help?
Thanks.
Take a look on this snippet
public class Evaluator
{
public void Eval(string Code)
{
Microsoft.CSharp.CSharpCodeProvider Provider = new Microsoft.CSharp.CSharpCodeProvider(); // Create an provider
System.CodeDom.Compiler.ICodeCompiler Compiler = Provider.CreateCompiler(); // Create An Compiler
System.CodeDom.Compiler.CompilerParameters Parameters = new System.CodeDom.Compiler.CompilerParameters(); // Create a parameters of the compiler
Parameters.GenerateInMemory = true; // It should generate the compiled assembly in the memory
System.CodeDom.Compiler.CompilerResults Results = Compiler.CompileAssemblyFromSource(Parameters, Code); //Compile it
///Now you just need to use reflection to call its methods
object SomeClass = Results.CompiledAssembly.CreateInstance("ClassName"); //Name of the class you want to create an instance
var Method = SomeClass.GetType().GetMethod("MethodName"); //Name of the Method you want to call
Method.Invoke(SomeClass, null); // change null for the argument it needs
}
}
if you want to just write code you will have to add the an class and a Method to wrap the user code and then you call it through the Invoke, you will probably have to reference your own assembly into this assembly
I have program with all DLLs hidden inside of one executable file. I am developing plugin support for this program.
All DLL in exe are stored in as Embedded Resources. Following code is used to access these embeded resources:
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
var resourceName = Assembly.GetExecutingAssembly()
.GetManifestResourceNames()
.FirstOrDefault(x => x.EndsWith(new AssemblyName(args.Name).Name + ".dll"));
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
if (stream == null)
return null;
var assemblyData = new byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
Plugins are loaded in separate domain for possibility to unload them:
public static T CreateInstanceInNewAppDomain<T>(bool shadowCopy = true)
{
var cdSetupInf = AppDomain.CurrentDomain.SetupInformation;
var separateDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), null,
new AppDomainSetup()
{
LoaderOptimization = LoaderOptimization.MultiDomain,
ApplicationBase = cdSetupInf.ApplicationBase,
PrivateBinPath = cdSetupInf.PrivateBinPath,
ShadowCopyFiles = shadowCopy ? "true" : "false"
});
var type = typeof(T);
return (T)separateDomain.CreateInstanceFromAndUnwrap(type.Assembly.Location, type.FullName);
}
The most important part of previous code is call „CreateInstanceFromAndUnwrap“ for creation object on separate domain. This part of code would work well if DLL containing type would be on HDD. Since it is loaded from Embedded Resources the assemblyFile parameter (represented as type.Assembly.Location) is empty. Therefore I am not able to create instance of my IPluginAccessor which I am using for accessing functionality in plugins. Is there any way how can create instance of type in separate domain without need to specify assemblyName? It would be great if there would be something like AppDomain.CreateInstanceFromAndUnwrap(Type type). If I looked well, there is only Activator.CreateInstance(Type type) but this works for current domain and not one I specify.
Thanks a lot
I think you can use Callback which will be executed in the new AppDomain.
Define an helper class:
class AnotherAppDomainPluginBuilder<T> : MarshalByRefObject
where T : new()
{
T Result { get; set; }
public void Create()
{
LoadRelevantDlls();
this.Result = new T();
}
void LoadRelevantDlls()
{
// load whatever DLLs in whatever way you would like to
}
}
Then instead of:
return (T)separateDomain.CreateInstanceFromAndUnwrap(type.Assembly.Location, type.FullName);
Write:
AnotherAppDomainPluginBuilder<T> builder =
(T)separateDomain.CreateInstanceFromAndUnwrap(
Assembly.CurrentAssembly,
typeof(AnotherAppDomainPluginBuilder<T> ));
separateDomain.DoCallback(builder.Create);
return builder.Result;
i want to display value of sharepoint people/group value in people editor(web part) when the page is loaded. This is the code that i use to get the value displayed in web part
if(SPContext .Current .ListItem .ID >= 1)
using (SPSite site = new SPSite("sitename"))
{
using (SPWeb web = site.OpenWeb())
{
var id = SPContext.Current.ListItem.ID;
SPList lists = web.Lists["DDClist"];
SPListItem item = lists.GetItemById(id);
{
string test = Convert.ToString(item["Project No"]);
tb_pno.Text = test;
string test2 = Convert.ToString(item["Project Title"]);
tb_pname.Text = test2;
string test3 = Convert.ToString(item["DDC No"]);
tb_idcno.Text = test3;
string test4 = Convert.ToString(item["Date In"]);
TextBox3.Text = test4;
}
}
}
is there a way to do the same thing with people editor?
This is all a little tricky; when I've had to do it before, I use the following to get SPUser object out of a field:
SPUser singleUser = new SPFieldUserValue(
item.Web, item["Single User"] as string).User;
SPUser[] multipleUsers = ((SPFieldUserValueCollection)item["MultipleUsers"])
.Cast<SPFieldUserValue>().Select(f => f.User);
I'm not sure why one user is stored as a string, but multiple users are stored as a specific object; it may also not be consistent in this so you might have to debug a bit and see what the type in your field is.
Once you have these SPUsers, you can populate your PeopleEditor control
using the account names as follows (quite long-winded):
ArrayList entityArrayList = new ArrayList();
foreach(SPUser user in multipleUsers) // or just once for a single user
{
PickerEntity entity = new PickerEntity;
entity.Key = user.LoginName;
entity = peMyPeople.ValidateEntity(entity);
entityArrayList.Add(entity);
}
peMyPeople.UpdateEntities(entityArrayList);
This also performs validation of the users of some kind.
If the page this control appears on may be posted-back, you need the following to be done during the postback in order for the values to be correctly roundtripped; I put it in PreRender but it could happen elsewhere in the lifecycle:
protected override void OnPreRender(EventArgs e)
{
if (IsPostBack)
{
var csa = peMyPeople.CommaSeparatedAccounts;
csa = peMyPeople.CommaSeparatedAccounts;
}
}
If you want to check any error messages that the control generates for you (if the user input is incorrect), you need to have done this switchout already:
var csa = usrBankSponsor.CommaSeparatedAccounts;
csa = usrOtherBankParties.CommaSeparatedAccounts;
//ErrorMessage is incorrect if you haven't done the above
if (!String.IsNullOrEmpty(usrBankSponsor.ErrorMessage))
{
...
}
It's really not very nice and there may be a much better way of handling it, but this is the result of my experience so far so hopefully it will save you some time.