So this particular topic has been beaten to death; but apparently my iteration is either not the method of choice or isn't practical for implementation.
The goal is to create a Windows Form and a Web Form. Those two forms; set a property in a separate class. Then other classes reference the container; that way as the interface is changed the functionality will change without a lot of recoding.
Windows Form ---> Container <--- Web Form
Container --> Referenced by these: Class 1, Class 2, Class 3
I approached it like this:
Form:
private Some.Reference.ToClass.Container _container;
public void Method(Some.Reference.ToClass.Container Container)
{
_container = Container;
}
private void button_click(object sender, EventArgs e)
{
_container.Name = textbox.Text (or some other component)
}
Class: "Container"
public Name { get; set; }
Class or Form to Reference:
Class WhateverName
{
private string REFERENCE;
private Some.Reference.ToClass.Container _container;
public void Method(Some.Reference.ToClass.Container Container)
{
_container = Container;
}
public void NewMethod()
{
REFERENCE = _container.Name;
}
}
It continually doesn't set; it states it's a null object. What am I missing? Any help would be appreciated. Or even a nice tutorial for me to compare to learn; or find why it doesn't work would be fine as well.
Based on the details provided; including the issue with the null value. I set a Constructor to automatically initialize based upon the change. Then just added some null reference check.
An example of this resolution:
public class One
{
// declared:
private.some.Reference.ToSomeClass _container;
One(ToSomeClass container)
{
_container = container;
}
private void button_click(object sender, EventArgs e)
{
if(_container != null)
{
_container.Name = textbox.Text (or some other component)
}
}
}
Then in the other class; it references the Property; for it to be set. So to avoid it failing cause a value hasn't been assigned yet or an instance hasn't been created just added a null reference verification.
Related
I have a .NET 5.0 web application that instantiates classes for each of the endpoints. Those classes instantiate child classes. Is there a more elegant or efficient way to access parent instance data from child instances besides the way I'm doing it right now?
As an example:
public class ComponentClass
{
private PageClass _page;
public ComponentClass(PageClass page)
{
_page = page;
}
public void ComponentMethod()
{
// Call the method from the parent instance
page.PageMethod();
}
}
public class PageClass
{
private ComponentClass _component;
public PageClass()
{
_component = new ComponentClass(this);
}
public async Task ProcessRequest(HttpContext context)
{
// Call the component's method
_component.ComponentMethod();
}
public void PageMethod()
{
// Do something here
}
}
Specifically, I'm trying to avoid having to pass this to every ComponentClass instance...
If you want to call a method on the parent, then you have two options. The first is to pass a reference of the parent into the child. There's no way around this, an object has no way to know in which object it is referenced from. In fact, it could be referenced by multiple parent objects.
The better solution is to use events. That way the child never knows anything about the parent(s) and can emit events that any number of components can subscribe to. See here for more details on events. For example, your component could look something like this:
public class Component
{
public event EventHandler Tick;
public void DoSomething()
{
EventHandler handler = Tick;
handler?.Invoke(this, new EventArgs());
}
}
And your PageClass:
public class PageClass
{
public Component _component { get; set; }
public void Init()
{
_component = new Component();
_component.Tick += Component_Tick;
}
public void MakeComponentTick()
{
// This method is just for testing, it's likely this would be triggered by user input
_component.DoSomething();
}
private void Component_Tick(object sender, EventArgs e)
{
Console.WriteLine("Component ticked!");
}
}
I have this class:
public class Observador : iObservador
{
private List<Form> Forms = new List<Form>();
public void DeSubscribirse(Form form)
{
Forms.Remove(form);
}
public void Limpiar()
{
Forms.Clear();
}
public void Subscribirse(Form form)
{
Forms.Add(form);
}
public List<Form> DevolverSubscriptos()
{
return this.Forms;
}
}
Which is used on a base form I have like this:
public partial class FormBase : Form
{
public EE.Observador Watcher = new Observador();
public FormBase()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
}
}
Which I use for the rest of my forms to be inherited from.
My idea is to have in all the forms a reference to the object Watcher from every place, with it having a reference for every form which is subscribed to it. So I can do for example, from FormB know that FormA is already subscribed with the method DevolverSubscriptos() (this means return subscribers) and access it to make it visible again after closing FormB.
The problem is that when I start FormB the list of Watcher with the whole forms is set back to 0.
What am I doing wrong? How can I solve it?
public partial class AdminUIGI : FormBase.FormBase
That's how I reference it.
Short answer: you're using an instance field. Each form is a separate instance, hence each has it's own copy of the EE.Observador.
So a quick and dirty fix would be to make this field static, i.e. shared by all instances of the given class. And if you want to improve, you might then consider reading about the Singleton pattern (mainly because you'll see it used a lot - but read on :) ), then read why using Singleton as a global variable is in fact an anti-pattern and move on to reading about dependency injection and IoC - which is how (in vacuum at least) your code should probably end up. (Note: for a quick and dirty solution static field is all you need).
#decPL I made it work with the singleton pattern doing this ` public sealed class Singleton
{
Singleton()
{
}
private static readonly object padlock = new object();
private static Singleton instance = null;
public static EE.Observador watcher = new Observador();
private Usuario userInstance = null;`
I use unity container in my WinForms application and register interfaces and classes. but when open other forms it's not working for fetching data. It's just working for form1.
How to resolve all forms?
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
RegisterType(new UnityContainer());
}
public static void RegisterType(IUnityContainer container)
{
container.RegisterType<IBlogRepository, BlogRepository>();
container.RegisterType<IPostRepository, PostRepository>();
Application.Run(container.Resolve<Form1>());
}
}
This is constructor injection in form1():
public partial class Form1: Form
{
public Form1()
{
InitializeComponent();
}
private readonly IBlogRepository _blogRepository;
public Form1(IBlogRepository blogRepository) : this()
{
_blogRepository = blogRepository;
}
}
and this is constructor injection in formAddUpdate():
public partial class FormAddUpdate : Form
{
public FormAddUpdate()
{
InitializeComponent();
}
private readonly IBlogRepository _blogRepository;
private readonly IPostRepository _postRepository;
public FormAddUpdate(IBlogRepository blogRepository, IPostRepository postRepository) : this()
{
_blogRepository = blogRepository;
_postRepository = postRepository;
}
}
now when the run application I can retrieve data from from1 but when switch to add/update form, it returns error: {"Object reference not set to an instance of an object."}
How to resolve all forms in my application?
If you look at your code, you resolve exactly one type (Form1) from your container. After that, poor container dies.
RegisterType(new UnityContainer());
}
public static void RegisterType(IUnityContainer container)
{
container.RegisterType<IBlogRepository, BlogRepository>();
container.RegisterType<IPostRepository, PostRepository>();
Application.Run(container.Resolve<Form1>());
}
When you create another container somewhere else to resolve, say, Form2 it knows nothing of the registrations made with the first container, so it can resolve neither BlogRepository nor PostRepository.
So the solution is to keep the one and only container around, the one that you do all registrations with. And use that one to do all your resolving, preferentially not by passing the container around or referencing a static service locator, but instead resolve just one root object and inject factories that do all the resolving needed.
I follow official guide to use simple injector to inject object in web form and it works, but now i cant make it works in custon control
this is what i do:
public partial class GestioneAttivita_cnStruttureSocieta : System.Web.UI.UserControl
{
[Import]
public IUnitOfWork iuow { get; set; }
public Domain.Entity.Attivita attivitaGestita {get; set;}
protected void Page_Load(object sender, EventArgs e)
{
using (iuow)
{
attivitaGestita = iuow.Attivita.Read(attivitaGestita.IdAttivita);
}
}
}
but i get null reference exception since iuow is null
i try to edit global.asax to manage UserControl in this way:
private static void RegisterWebPages(Container container)
{
var pageTypes =
from assembly in BuildManager.GetReferencedAssemblies().Cast<Assembly>()
where !assembly.IsDynamic
where !assembly.GlobalAssemblyCache
from type in assembly.GetExportedTypes()
where (type.IsSubclassOf(typeof(Page)) **|| type.IsSubclassOf(typeof(UserControl)))**
where !type.IsAbstract && !type.IsGenericType
select type;
foreach (Type type in pageTypes)
{
var registration = Lifestyle.Transient.CreateRegistration(type, container);
registration.SuppressDiagnosticWarning(
DiagnosticType.DisposableTransientComponent,
"ASP.NET creates and disposes page classes for us.");
container.AddRegistration(type, registration);
}
}
}
class ImportAttributePropertySelectionBehavior : IPropertySelectionBehavior {
public bool SelectProperty(Type serviceType, PropertyInfo propertyInfo) {
// Makes use of the System.ComponentModel.Composition assembly
bool _return = false;
_return = (typeof(Page).IsAssignableFrom(serviceType) &&
propertyInfo.GetCustomAttributes<ImportAttribute>().Any())
**||
(typeof(UserControl).IsAssignableFrom(serviceType) &&
propertyInfo.GetCustomAttributes<ImportAttribute>().Any());**
return _return;
}
}
but i get same error
is this doable?
To be able to get this working, you will have to hook onto the PreLoad event of the page during initialization. During PreLoad you can walk the page's control hierarchy and initialize all controls like you do with the page itself.
There's actually example code in the Simple Injector repository (that never made it to an official package) that shows you how to do this. Take a look here.
I'm working on an application that supports various plugins (well, that's planned at least). And I'd love to have it beautiful.
So I want to let the plugin developer send a big control (like a panel or other containers) to my host application and have the user setup their settings for the plugin in the application.
That would take the plugin-developer's effort to somehow implement a settings-panel that runs by in an own window.
Thing is, I'm not sure how to do that.
I can pass variables to my host application but as soon as I try to add the control to my container panel, I get a RemoteException, telling me that the field 'parent' on type 'System.Windows.Forms.Control' can't be found.
I tried to add the plugin-control that way:
panel.Controls.Add(pluginControl);
If I try it the other way around:
pluginControl.Parent = panel;
I get a SerializationException because the class System.Windows.Forms.Control isn't marked Serializable.
Maybe some person ran into the same thing and can help me.
Let me know if you need more information!
Edit: Have a look on my current implementation: https://dl.dropboxusercontent.com/u/62845853/Random%20crap/NotModified_SamplePluginSystem.zip
I tried something which you can adorn to your needs:
First i created a PluginBase class and the proper EventArgs in a ClassLibrary:
public abstract class PluginBase
{
public abstract void Initialize();
protected void showControl(UserControl control)
{
ShowControl(this, new ControlToBeShownEventArgs() { TheControl = control });
}
public event EventHandler<ControlToBeShownEventArgs> ShowControl = delegate { };
}
public class ControlToBeShownEventArgs : EventArgs
{
public UserControl TheControl { get; set; }
}
This library is referenced by every Plugin and by the host application.
The Plugin is in turn also a Class Library (build path set to the one of the host)
inside i made a plugin inheriting this base type:
class SomePlugin : PluginBase
{
public override void Initialize()
{
showControl(new UserControl1());
}
}
The UserControl1 is the Control to be shown.
Done that, I next added the following code to the main window of the host:
List<PluginBase> plugins = new List<PluginBase>();
private void Form1_Load(object sender, EventArgs e) //Hook in the event too
{
DirectoryInfo dir = (new FileInfo(Assembly.GetExecutingAssembly().Location)).Directory;
foreach (var item in dir.GetFiles())
{
if (item.Name.Contains("Plugin") && item.Name.EndsWith(".dll"))
{
Assembly ass = Assembly.LoadFile(item.FullName);
foreach (Type type in ass.GetTypes().Where(t => t.BaseType.Name == "PluginBase"))
{
PluginBase pibase = (PluginBase)Activator.CreateInstance(type,false);
plugins.Add(pibase);
}
}
}
foreach (var item in plugins)
{
item.ShowControl += item_ShowControl;
item.Initialize();
}
}
void item_ShowControl(object sender, ControlToBeShownEventArgs e)
{
this.Controls.Add(e.TheControl);
}