I have a conceptual / theoretical question about loose coupling and interfaces.
So one way to use an interface might be to encapsulate the parameters required by a certain constructor:
class Foo
{
public Foo(IFooInterface foo)
{
// do stuff that depends on the members of IFooInterface
}
}
So as long as the object passed in implements the contract, everything will work. From my understanding the main benefit here is that it enables polymorphism, but I'm not sure whether this really has anything to do with loose coupling.
Lets say for the sake of argument that an IFooInterface is as follows:
interface IFooInterface
{
string FooString { get; set; }
int FooInt { get; set; }
void DoFoo(string _str);
}
From a loose coupling standpoint, wouldnt it much better to NOT to use an IFooInterface in the above constructor, and instead set up the Foo like so:
class Foo
{
public Foo(string _fooString, int _fooInt, Action<string> _doFoo)
{
// do the same operations
}
}
Because say I want to drop the functionality of Foo into another project. That means that other project also has to reference IFooInterface, adding another dependency. But this way I can drop Foo into another project and it expresses exactly what it requires in order to work. Obviously I can just use overloaded constructors, but lets say for the sake of argument I dont want to and/or cannot modify Foo's constructors.
The most salient downside (to me atleast) is that if you have a method with a bunch of primitive parameters it gets ugly and hard to read. So I had the idea to create a sort of wrapping function that allows you to still pass in an interface rather than all the primitive types:
public static Func<T, R> Wrap<T, R>(Func<T, object[]> conversion)
{
return new Func<T, R>(t =>
{
object[] parameters = conversion(t);
Type[] args = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
args[i] = parameters[i].GetType();
}
ConstructorInfo info = typeof(R).GetConstructor(args);
return (R)info.Invoke(parameters);
});
}
The idea here is that I can get back a function that takes an instance of some interface which conforms to the requirements of Foo, but Foo literally doesnt know anything about that interface. It could be used like so:
public Foo MakeFoo(IFooInterface foo)
{
return Wrap<IFooInterface, Foo>(f =>
new object[] { f.FooString, f.FooInt, f.DoFoo })(foo);
}
I've heard discussion about how interfaces are supposed to enable loose-coupling, but was wondering about this.
Wondering what some experienced programmers think.